diff --git a/src/kernel/scheduler.rs b/src/kernel/scheduler.rs index 07c3506..7071fbb 100644 --- a/src/kernel/scheduler.rs +++ b/src/kernel/scheduler.rs @@ -3,12 +3,12 @@ use std::rc::Rc; use crate::utility::list::List; use crate::kernel::thread::Thread; -use super::system::System; use super::thread_manager::ThreadManager; #[derive(PartialEq)] pub struct Scheduler { - ready_list: List>> + ready_list: List>>, + pub thread_manager: Option>> } impl Scheduler { @@ -18,7 +18,8 @@ impl Scheduler { /// Initilize the list of ready thread pub fn new() -> Self { Self { - ready_list: List::new() + ready_list: List::new(), + thread_manager: Option::None } } @@ -53,17 +54,21 @@ impl Scheduler { /// ## Parameter /// /// **next_thread** thread to dispatch to the CPU - pub fn switch_to(&mut self, system: &mut System, next_thread: Rc>) { - let thread_manager = system.get_thread_manager(); - if let Some(old_thread) = thread_manager.get_g_current_thread() { - thread_manager.thread_save_processor_state(system, Rc::clone(&old_thread)); - // old_thread.save_simulator_state(); + pub fn switch_to(&mut self, next_thread: Rc>) { + if let Some(tm) = &self.thread_manager { + let rc = Rc::clone(&tm); + if let Some(old_thread) = tm.borrow_mut().get_g_current_thread() { + rc.borrow_mut().thread_save_processor_state(Rc::clone(&old_thread)); + // old_thread.save_simulator_state(); - if old_thread != &next_thread { - thread_manager.thread_restore_processor_state(system, Rc::clone(&next_thread)); - // next_thread.restore_simulator_state(); - thread_manager.set_g_current_thread(Option::Some(next_thread)); + if old_thread != &next_thread { + rc.borrow_mut().thread_restore_processor_state(Rc::clone(&next_thread)); + // next_thread.restore_simulator_state(); + rc.borrow_mut().set_g_current_thread(Option::Some(next_thread)); + } } + } else { + panic!("thread manager shouldn't be none"); } } } \ No newline at end of file diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 027cfce..f5741f7 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -40,17 +40,22 @@ impl Semaphore { /// Note that thread_manager::thread_sleep assumes that interrupts are disabled /// when it is called. /// - /// ### Parameters + /// ### Parameters TODO Refaire /// - *current_thread* the current thread /// - *machine* the machine where the threads are executed - pub fn p(&mut self, current_thread: Rc>, system: Rc>) { - let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff); + pub fn p(&mut self, system: &mut System) { + let old_status = system.get_machine().interrupt.set_status(InterruptOff); self.counter -= 1; if self.counter < 0 { - self.waiting_queue.push(Rc::clone(¤t_thread)); - self.thread_manager.borrow_mut().thread_sleep(current_thread); + match system.get_thread_manager().get_g_current_thread() { + Some(thread) => { + self.waiting_queue.push(Rc::clone(thread)); + system.get_thread_manager().thread_sleep(system, Rc::clone(thread)); + }, + None => unreachable!("Current thread should not be None") + } } - system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } /// Increment semaphore value, waking up a waiting thread if any. @@ -63,13 +68,13 @@ impl Semaphore { /// ### Parameters /// - **machine** the machine where the threads are executed /// - **scheduler** the scheduler which determine which thread to execute - pub fn v(&mut self, system: Rc>){ - let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff); + pub fn v(&mut self, system: &mut System){ + let old_status = system.get_machine().interrupt.set_status(InterruptOff); self.counter += 1; if self.waiting_queue.peek() != None { - system.borrow_mut().get_thread_manager().borrow_mut().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); } - system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } } @@ -111,23 +116,30 @@ impl Lock { /// ### Parameters /// - **current_thread** the current thread /// - **machine** the machine where the threads are executed - pub fn acquire(&mut self, current_thread: Option>>, system: Rc>) { - let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff); + pub fn acquire(&mut self, system: &mut System) { + let old_status = system.get_machine().interrupt.set_status(InterruptOff); if self.free { self.free = false; - self.owner = current_thread; - } else { - match current_thread { - Some(x) => { - self.waiting_queue.push(Rc::clone(&x)); - self.thread_manager.borrow_mut().thread_sleep(x) + self.owner = Option::Some(match system.get_thread_manager().get_g_current_thread() { + Some(th) => { + Rc::clone(th) }, - None => () + None => unreachable!() + }); + } else { + let t = system.get_thread_manager().get_g_current_thread(); + match t { + Some(x) => { + let x = Rc::clone(x); + self.waiting_queue.push(Rc::clone(&x)); + system.thread_sleep(Rc::clone(&x)); + }, + None => unreachable!("Current thread should not be None") } } - system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } /// Wake up a waiter if necessary, or release it if no thread is waiting. @@ -139,31 +151,37 @@ impl Lock { /// ### Parameters /// - **machine** the machine where the code is executed /// - **scheduler** the scheduler which determine which thread to execute - pub fn release(&mut self, system: Rc>, current_thread: Rc>) { - let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff); + pub fn release(&mut self, system: &mut System) { + let old_status = system.get_machine().interrupt.set_status(InterruptOff); - if self.held_by_current_thread(current_thread) { - if self.waiting_queue.peek() != None { - self.owner = Some(self.waiting_queue.pop().unwrap()); - let sys = system.borrow_mut(); - let tm = sys.get_thread_manager(); - let scheduler = &mut tm.borrow_mut().g_scheduler; - match &self.owner { - Some(x) => scheduler.ready_to_run(Rc::clone(&x)), - None => () + match system.get_thread_manager().get_g_current_thread() { + Some(thread) => { + if self.held_by_current_thread(system) { + if self.waiting_queue.peek() != None { + self.owner = Some(self.waiting_queue.pop().unwrap()); + match &self.owner { + Some(x) => system.get_thread_manager().g_scheduler.ready_to_run(Rc::clone(&x)), + None => () + } + } else { + self.free = true; + self.owner = None; + } } - } else { - self.free = true; - self.owner = None; } + None => () } - system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } - pub fn held_by_current_thread(&mut self, current_thread: Rc>) -> bool { + pub fn held_by_current_thread(&mut self, system: &mut System) -> bool { match &self.owner { - Some(x) => Rc::ptr_eq(&x, ¤t_thread), + Some(x) => + match system.get_thread_manager().get_g_current_thread() { + Some(thread) => Rc::ptr_eq(&x, thread), + None => false + } None => false } } @@ -195,11 +213,11 @@ impl Condition { /// ### Parameters /// - **current_thread** the current thread /// - **machine** the machine where threads are executed - pub fn wait(&mut self, current_thread: Rc>, machine: &mut Machine) { + pub fn wait(&mut self, current_thread: Rc>, machine: &mut Machine, system: &mut System) { let old_status = machine.interrupt.set_status(InterruptOff); self.waiting_queue.push(Rc::clone(¤t_thread)); - self.thread_manager.borrow_mut().thread_sleep(current_thread); + self.thread_manager.borrow_mut().thread_sleep(system, current_thread); machine.interrupt.set_status(old_status); } diff --git a/src/kernel/system.rs b/src/kernel/system.rs index e3aaf73..7383911 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -6,7 +6,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::simulator::machine::Machine; -use super::thread_manager::ThreadManager; +use super::{thread_manager::ThreadManager, thread::Thread}; /// This macro properly initializes the system #[macro_export] @@ -46,17 +46,23 @@ impl System { } } + /// Sets a thread asleep + /// + pub fn thread_sleep(&mut self, thread: Rc>) { + &self.thread_manager.thread_sleep(self, thread); + } + // GETTERS /// Returns the Machine /// /// Useful to access RAM, devices, ... - pub fn get_machine(&self) -> &Machine { - &self.machine + pub fn get_machine(&mut self) -> &mut Machine { + &mut self.machine } - pub fn get_thread_manager(&self) -> &ThreadManager { - &self.thread_manager + pub fn get_thread_manager(&mut self) -> &mut ThreadManager { + &mut self.thread_manager } // Setters diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 5820906..2d5cc06 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -70,7 +70,7 @@ impl ThreadManager { if let Some(next_thread) = next_thread { let scheduler = &mut self.g_scheduler; scheduler.ready_to_run(thread); - scheduler.switch_to(system, next_thread); + scheduler.switch_to(next_thread); } machine.interrupt.set_status(old_status); } @@ -86,7 +86,7 @@ impl ThreadManager { machine.interrupt.idle(); next_thread = self.g_scheduler.find_next_to_run(); } - self.g_scheduler.switch_to(system, Rc::clone(&next_thread.unwrap())); + self.g_scheduler.switch_to(Rc::clone(&next_thread.unwrap())); } /// Finish the execution of the thread and prepare its deallocation