Moved to reference passing system
This commit is contained in:
parent
abb97d17d5
commit
1906ec836c
@ -3,12 +3,12 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use crate::utility::list::List;
|
use crate::utility::list::List;
|
||||||
use crate::kernel::thread::Thread;
|
use crate::kernel::thread::Thread;
|
||||||
|
use super::system::System;
|
||||||
use super::thread_manager::ThreadManager;
|
use super::thread_manager::ThreadManager;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct Scheduler {
|
pub struct Scheduler {
|
||||||
ready_list: List<Rc<RefCell<Thread>>>,
|
ready_list: List<Rc<RefCell<Thread>>>
|
||||||
pub thread_manager: Option<Rc<RefCell<ThreadManager>>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scheduler {
|
impl Scheduler {
|
||||||
@ -18,8 +18,7 @@ impl Scheduler {
|
|||||||
/// Initilize the list of ready thread
|
/// Initilize the list of ready thread
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ready_list: List::new(),
|
ready_list: List::new()
|
||||||
thread_manager: Option::None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,21 +53,17 @@ impl Scheduler {
|
|||||||
/// ## Parameter
|
/// ## Parameter
|
||||||
///
|
///
|
||||||
/// **next_thread** thread to dispatch to the CPU
|
/// **next_thread** thread to dispatch to the CPU
|
||||||
pub fn switch_to(&mut self, next_thread: Rc<RefCell<Thread>>) {
|
pub fn switch_to(&mut self, system: &mut System, next_thread: Rc<RefCell<Thread>>) {
|
||||||
if let Some(tm) = &self.thread_manager {
|
let thread_manager = system.get_thread_manager();
|
||||||
let rc = Rc::clone(&tm);
|
if let Some(old_thread) = thread_manager.get_g_current_thread() {
|
||||||
if let Some(old_thread) = tm.borrow_mut().get_g_current_thread() {
|
thread_manager.thread_save_processor_state(system, Rc::clone(&old_thread));
|
||||||
rc.borrow_mut().thread_save_processor_state(Rc::clone(&old_thread));
|
// old_thread.save_simulator_state();
|
||||||
// old_thread.save_simulator_state();
|
|
||||||
|
|
||||||
if old_thread != &next_thread {
|
if old_thread != &next_thread {
|
||||||
rc.borrow_mut().thread_restore_processor_state(Rc::clone(&next_thread));
|
thread_manager.thread_restore_processor_state(system, Rc::clone(&next_thread));
|
||||||
// next_thread.restore_simulator_state();
|
// next_thread.restore_simulator_state();
|
||||||
rc.borrow_mut().set_g_current_thread(Option::Some(next_thread));
|
thread_manager.set_g_current_thread(Option::Some(next_thread));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
panic!("thread manager shouldn't be none");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,10 +16,7 @@ macro_rules! init_system {
|
|||||||
init_system!(m)
|
init_system!(m)
|
||||||
}};
|
}};
|
||||||
($a:expr) => {{
|
($a:expr) => {{
|
||||||
let sys = std::rc::Rc::new(std::cell::RefCell::new(crate::System::new($a)));
|
$crate::System::new($a)
|
||||||
crate::System::freeze(std::rc::Rc::clone(&sys));
|
|
||||||
sys
|
|
||||||
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +33,7 @@ macro_rules! init_system {
|
|||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct System {
|
pub struct System {
|
||||||
machine: Machine,
|
machine: Machine,
|
||||||
thread_manager: Rc<RefCell<ThreadManager>>
|
thread_manager: ThreadManager
|
||||||
}
|
}
|
||||||
|
|
||||||
impl System {
|
impl System {
|
||||||
@ -45,34 +42,26 @@ impl System {
|
|||||||
pub fn new(machine: Machine) -> System {
|
pub fn new(machine: Machine) -> System {
|
||||||
Self {
|
Self {
|
||||||
machine,
|
machine,
|
||||||
thread_manager: Rc::new(RefCell::new(ThreadManager::new()))
|
thread_manager: ThreadManager::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// use thread_manager setter to send it system instance
|
|
||||||
pub fn freeze(this: Rc<RefCell<System>>) {
|
|
||||||
let copy = Rc::clone(&this);
|
|
||||||
let tm = &this.borrow_mut().thread_manager;
|
|
||||||
tm.borrow_mut().system = Option::Some(copy);
|
|
||||||
ThreadManager::freeze(tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GETTERS
|
// GETTERS
|
||||||
|
|
||||||
/// Returns the Machine
|
/// Returns the Machine
|
||||||
///
|
///
|
||||||
/// Useful to access RAM, devices, ...
|
/// Useful to access RAM, devices, ...
|
||||||
pub fn get_machine(&self) -> Machine {
|
pub fn get_machine(&self) -> &Machine {
|
||||||
self.machine
|
&self.machine
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_thread_manager(&self) -> Rc<RefCell<ThreadManager>> {
|
pub fn get_thread_manager(&self) -> &ThreadManager {
|
||||||
Rc::clone(&self.thread_manager)
|
&self.thread_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
|
|
||||||
/// Assign a machine to the system
|
/// Assign a machine to the system
|
||||||
pub fn set_machine(&mut self, machine: Machine) {
|
pub fn set_machine(&mut self, machine: Machine) {
|
||||||
self.machine = machine
|
self.machine = machine
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,6 @@ impl ThreadManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn freeze(this: &Rc<RefCell<ThreadManager>>) {
|
|
||||||
let copy = Rc::clone(this);
|
|
||||||
this.borrow_mut().g_scheduler.thread_manager = Option::Some(copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Start a thread, attaching it to a process
|
/// Start a thread, attaching it to a process
|
||||||
pub fn start_thread(&mut self, thread: Rc<RefCell<Thread>>, owner: Process, func_pc: i64, argument: i64) -> Result<(), ErrorCode> {
|
pub fn start_thread(&mut self, thread: Rc<RefCell<Thread>>, owner: Process, func_pc: i64, argument: i64) -> Result<(), ErrorCode> {
|
||||||
let mut thread_m = thread.borrow_mut();
|
let mut thread_m = thread.borrow_mut();
|
||||||
@ -57,93 +52,71 @@ impl ThreadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for another thread to finish its execution
|
/// Wait for another thread to finish its execution
|
||||||
pub fn thread_join(&mut self, id_thread: Rc<RefCell<Thread>>) {
|
pub fn thread_join(&mut self, system: &mut System, id_thread: Rc<RefCell<Thread>>) {
|
||||||
while self.get_g_alive().contains(&Rc::clone(&id_thread)) {
|
while self.get_g_alive().contains(&Rc::clone(&id_thread)) {
|
||||||
self.thread_yield(Rc::clone(&id_thread));
|
self.thread_yield(system, Rc::clone(&id_thread));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Relinquish the CPU if any other thread is runnable.
|
/// Relinquish the CPU if any other thread is runnable.
|
||||||
///
|
///
|
||||||
/// Cannot use yield as a function name -> reserved name in rust
|
/// Cannot use yield as a function name -> reserved name in rust
|
||||||
pub fn thread_yield(&mut self, thread: Rc<RefCell<Thread>>) {
|
pub fn thread_yield(&mut self, system: &mut System, thread: Rc<RefCell<Thread>>) {
|
||||||
if let Some(system) = &self.system {
|
let mut machine = system.get_machine();
|
||||||
let sys = system.borrow_mut();
|
let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff);
|
||||||
let mut machine = sys.get_machine();
|
|
||||||
let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff);
|
|
||||||
|
|
||||||
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
||||||
let next_thread = self.g_scheduler.find_next_to_run();
|
let next_thread = self.g_scheduler.find_next_to_run();
|
||||||
if let Some(next_thread) = next_thread {
|
if let Some(next_thread) = next_thread {
|
||||||
let scheduler = &mut self.g_scheduler;
|
let scheduler = &mut self.g_scheduler;
|
||||||
scheduler.ready_to_run(thread);
|
scheduler.ready_to_run(thread);
|
||||||
scheduler.switch_to(next_thread);
|
scheduler.switch_to(system, next_thread);
|
||||||
}
|
|
||||||
machine.interrupt.set_status(old_status);
|
|
||||||
}
|
}
|
||||||
|
machine.interrupt.set_status(old_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put the thread to sleep and relinquish the processor
|
/// Put the thread to sleep and relinquish the processor
|
||||||
pub fn thread_sleep(&mut self, thread: Rc<RefCell<Thread>>) {
|
pub fn thread_sleep(&mut self, system: &mut System, thread: Rc<RefCell<Thread>>) {
|
||||||
|
|
||||||
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
||||||
if let Some(system) = &self.system {
|
let machine = system.get_machine();
|
||||||
let sys = system.borrow_mut();
|
assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff);
|
||||||
let machine = sys.get_machine();
|
let mut next_thread = self.g_scheduler.find_next_to_run();
|
||||||
assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff);
|
while next_thread.is_none() {
|
||||||
|
eprintln!("Nobody to run => idle");
|
||||||
let mut next_thread = self.g_scheduler.find_next_to_run();
|
machine.interrupt.idle();
|
||||||
while next_thread.is_none() {
|
next_thread = self.g_scheduler.find_next_to_run();
|
||||||
eprintln!("Nobody to run => idle");
|
|
||||||
machine.interrupt.idle();
|
|
||||||
next_thread = self.g_scheduler.find_next_to_run();
|
|
||||||
}
|
|
||||||
self.g_scheduler.switch_to(Rc::clone(&next_thread.unwrap()));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
self.g_scheduler.switch_to(system, Rc::clone(&next_thread.unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish the execution of the thread and prepare its deallocation
|
/// Finish the execution of the thread and prepare its deallocation
|
||||||
pub fn thread_finish(&mut self, thread: Rc<RefCell<Thread>>) {
|
pub fn thread_finish(&mut self, system: &mut System, thread: Rc<RefCell<Thread>>) {
|
||||||
if let Some(system) = &self.system {
|
let mut machine = system.get_machine();
|
||||||
let sys = Rc::clone(system);
|
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||||
let sys = sys.borrow_mut();
|
self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread));
|
||||||
let mut machine = sys.get_machine();
|
self.g_alive.remove(Rc::clone(&thread));
|
||||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
// g_objets_addrs->removeObject(self.thread) // a ajouté plus tard
|
||||||
self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread));
|
self.thread_sleep(system, Rc::clone(&thread));
|
||||||
self.g_alive.remove(Rc::clone(&thread));
|
machine.interrupt.set_status(old_status);
|
||||||
// g_objets_addrs->removeObject(self.thread) // a ajouté plus tard
|
}
|
||||||
self.thread_sleep(Rc::clone(&thread));
|
|
||||||
machine.interrupt.set_status(old_status);
|
pub fn thread_save_processor_state(&mut self, system: &mut System, thread: Rc<RefCell<Thread>>) {
|
||||||
|
let mut t: RefMut<_> = thread.borrow_mut();
|
||||||
|
for i in 0..NUM_INT_REGS {
|
||||||
|
t.thread_context.int_registers[i] = system.get_machine().read_int_register(i);
|
||||||
|
}
|
||||||
|
for i in 0..NUM_FP_REGS {
|
||||||
|
t.thread_context.float_registers[i] = system.get_machine().read_fp_register(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thread_save_processor_state(&mut self, thread: Rc<RefCell<Thread>>) {
|
pub fn thread_restore_processor_state(&self, system: &mut System, thread: Rc<RefCell<Thread>>) {
|
||||||
if let Some(system) = &self.system {
|
|
||||||
let mut t: RefMut<_> = thread.borrow_mut();
|
|
||||||
let system = system;
|
|
||||||
for i in 0..NUM_INT_REGS {
|
|
||||||
t.thread_context.int_registers[i] = system.get_machine().read_int_register(i);
|
|
||||||
}
|
|
||||||
for i in 0..NUM_FP_REGS {
|
|
||||||
t.thread_context.float_registers[i] = system.get_machine().read_fp_register(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("System is None")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn thread_restore_processor_state(&self, thread: Rc<RefCell<Thread>>) {
|
let t: Ref<_> = thread.borrow();
|
||||||
if let Some(system) = &self.system {
|
for i in 0..NUM_INT_REGS {
|
||||||
let system = system.borrow_mut();
|
let machine = system.get_machine();
|
||||||
let t: Ref<_> = thread.borrow();
|
let mut machine = machine;
|
||||||
for i in 0..NUM_INT_REGS {
|
machine.write_int_register(i, t.thread_context.int_registers[i]);
|
||||||
let machine = system.get_machine();
|
|
||||||
let mut machine = machine;
|
|
||||||
machine.write_int_register(i, t.thread_context.int_registers[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("System is None")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,4 @@ use simulator::machine::Machine;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let machine = Machine::init_machine();
|
let machine = Machine::init_machine();
|
||||||
let system = Rc::new(RefCell::new(System::new(machine)));
|
let system = Rc::new(RefCell::new(System::new(machine)));
|
||||||
|
|
||||||
System::freeze(system);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user