From abb97d17d58d73687f2ce0e3975d0a2b6d8c0c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Wed, 15 Mar 2023 14:56:05 +0100 Subject: [PATCH 01/10] Removed Rc> --- src/kernel/system.rs | 12 ++++++------ src/kernel/thread_manager.rs | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/kernel/system.rs b/src/kernel/system.rs index c7748e7..5144956 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -35,7 +35,7 @@ macro_rules! init_system { /// - The scheduler which acts upon these threads #[derive(PartialEq)] pub struct System { - g_machine: RefCell, + machine: Machine, thread_manager: Rc> } @@ -44,7 +44,7 @@ impl System { /// System constructor pub fn new(machine: Machine) -> System { Self { - g_machine: RefCell::new(machine), + machine, thread_manager: Rc::new(RefCell::new(ThreadManager::new())) } } @@ -62,8 +62,8 @@ impl System { /// Returns the Machine /// /// Useful to access RAM, devices, ... - pub fn get_g_machine(&self) -> &RefCell { - &self.g_machine + pub fn get_machine(&self) -> Machine { + self.machine } pub fn get_thread_manager(&self) -> Rc> { @@ -73,8 +73,8 @@ impl System { // Setters /// Assign a machine to the system - pub fn set_g_machine(&mut self, machine: RefCell) { - self.g_machine = machine + pub fn set_machine(&mut self, machine: Machine) { + self.machine = machine } } diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 43e9776..6d0ddeb 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -69,7 +69,7 @@ impl ThreadManager { pub fn thread_yield(&mut self, thread: Rc>) { if let Some(system) = &self.system { let sys = system.borrow_mut(); - let mut machine = sys.get_g_machine().borrow_mut(); + 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); @@ -89,7 +89,7 @@ impl ThreadManager { assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); if let Some(system) = &self.system { let sys = system.borrow_mut(); - let machine = sys.get_g_machine().borrow_mut(); + let machine = sys.get_machine(); assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); let mut next_thread = self.g_scheduler.find_next_to_run(); @@ -108,7 +108,7 @@ impl ThreadManager { if let Some(system) = &self.system { let sys = Rc::clone(system); let sys = sys.borrow_mut(); - let mut machine = sys.get_g_machine().borrow_mut(); + let mut machine = sys.get_machine(); let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); self.g_alive.remove(Rc::clone(&thread)); @@ -121,12 +121,12 @@ impl ThreadManager { pub fn thread_save_processor_state(&mut self, thread: Rc>) { if let Some(system) = &self.system { let mut t: RefMut<_> = thread.borrow_mut(); - let system = system.borrow_mut(); + let system = system; for i in 0..NUM_INT_REGS { - t.thread_context.int_registers[i] = system.get_g_machine().borrow().read_int_register(i); + 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_g_machine().borrow().read_fp_register(i); + t.thread_context.float_registers[i] = system.get_machine().read_fp_register(i); } } else { unreachable!("System is None") @@ -138,8 +138,8 @@ impl ThreadManager { let system = system.borrow_mut(); let t: Ref<_> = thread.borrow(); for i in 0..NUM_INT_REGS { - let machine = system.get_g_machine(); - let mut machine = machine.borrow_mut(); + let machine = system.get_machine(); + let mut machine = machine; machine.write_int_register(i, t.thread_context.int_registers[i]); } } else { From 1906ec836ccaadc3adfd194d22598034fe43405d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Wed, 15 Mar 2023 15:20:20 +0100 Subject: [PATCH 02/10] Moved to reference passing system --- src/kernel/scheduler.rs | 29 ++++----- src/kernel/system.rs | 27 +++----- src/kernel/thread_manager.rs | 115 ++++++++++++++--------------------- src/main.rs | 2 - 4 files changed, 64 insertions(+), 109 deletions(-) diff --git a/src/kernel/scheduler.rs b/src/kernel/scheduler.rs index 7071fbb..07c3506 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>>, - pub thread_manager: Option>> + ready_list: List>> } impl Scheduler { @@ -18,8 +18,7 @@ impl Scheduler { /// Initilize the list of ready thread pub fn new() -> Self { Self { - ready_list: List::new(), - thread_manager: Option::None + ready_list: List::new() } } @@ -54,21 +53,17 @@ impl Scheduler { /// ## Parameter /// /// **next_thread** thread to dispatch to the CPU - 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(); + 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(); - 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)); - } + 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)); } - } else { - panic!("thread manager shouldn't be none"); } } } \ No newline at end of file diff --git a/src/kernel/system.rs b/src/kernel/system.rs index 5144956..e3aaf73 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -16,10 +16,7 @@ macro_rules! init_system { init_system!(m) }}; ($a:expr) => {{ - let sys = std::rc::Rc::new(std::cell::RefCell::new(crate::System::new($a))); - crate::System::freeze(std::rc::Rc::clone(&sys)); - sys - + $crate::System::new($a) }}; } @@ -36,7 +33,7 @@ macro_rules! init_system { #[derive(PartialEq)] pub struct System { machine: Machine, - thread_manager: Rc> + thread_manager: ThreadManager } impl System { @@ -45,34 +42,26 @@ impl System { pub fn new(machine: Machine) -> System { Self { 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>) { - let copy = Rc::clone(&this); - let tm = &this.borrow_mut().thread_manager; - tm.borrow_mut().system = Option::Some(copy); - ThreadManager::freeze(tm); - } - // GETTERS /// Returns the Machine /// /// Useful to access RAM, devices, ... - pub fn get_machine(&self) -> Machine { - self.machine + pub fn get_machine(&self) -> &Machine { + &self.machine } - pub fn get_thread_manager(&self) -> Rc> { - Rc::clone(&self.thread_manager) + pub fn get_thread_manager(&self) -> &ThreadManager { + &self.thread_manager } // Setters - /// Assign a machine to the system + /// Assign a machine to the system pub fn set_machine(&mut self, machine: Machine) { self.machine = machine } diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 6d0ddeb..5820906 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -36,11 +36,6 @@ impl ThreadManager { } } - pub fn freeze(this: &Rc>) { - let copy = Rc::clone(this); - this.borrow_mut().g_scheduler.thread_manager = Option::Some(copy); - } - /// Start a thread, attaching it to a process pub fn start_thread(&mut self, thread: Rc>, owner: Process, func_pc: i64, argument: i64) -> Result<(), ErrorCode> { let mut thread_m = thread.borrow_mut(); @@ -57,93 +52,71 @@ impl ThreadManager { } /// Wait for another thread to finish its execution - pub fn thread_join(&mut self, id_thread: Rc>) { + pub fn thread_join(&mut self, system: &mut System, id_thread: Rc>) { 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. /// /// Cannot use yield as a function name -> reserved name in rust - pub fn thread_yield(&mut self, thread: Rc>) { - if let Some(system) = &self.system { - let sys = system.borrow_mut(); - let mut machine = sys.get_machine(); - let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff); + pub fn thread_yield(&mut self, system: &mut System, thread: Rc>) { + let mut machine = system.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); - let next_thread = self.g_scheduler.find_next_to_run(); - if let Some(next_thread) = next_thread { - let scheduler = &mut self.g_scheduler; - scheduler.ready_to_run(thread); - scheduler.switch_to(next_thread); - } - machine.interrupt.set_status(old_status); + assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); + let next_thread = self.g_scheduler.find_next_to_run(); + if let Some(next_thread) = next_thread { + let scheduler = &mut self.g_scheduler; + scheduler.ready_to_run(thread); + scheduler.switch_to(system, next_thread); } + machine.interrupt.set_status(old_status); } /// Put the thread to sleep and relinquish the processor - pub fn thread_sleep(&mut self, thread: Rc>) { - + pub fn thread_sleep(&mut self, system: &mut System, thread: Rc>) { assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); - if let Some(system) = &self.system { - let sys = system.borrow_mut(); - let machine = sys.get_machine(); - assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); - - let mut next_thread = self.g_scheduler.find_next_to_run(); - while next_thread.is_none() { - 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())); - + let machine = system.get_machine(); + assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); + let mut next_thread = self.g_scheduler.find_next_to_run(); + while next_thread.is_none() { + eprintln!("Nobody to run => idle"); + machine.interrupt.idle(); + next_thread = self.g_scheduler.find_next_to_run(); } + self.g_scheduler.switch_to(system, Rc::clone(&next_thread.unwrap())); } /// Finish the execution of the thread and prepare its deallocation - pub fn thread_finish(&mut self, thread: Rc>) { - if let Some(system) = &self.system { - let sys = Rc::clone(system); - let sys = sys.borrow_mut(); - let mut machine = sys.get_machine(); - let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); - self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); - self.g_alive.remove(Rc::clone(&thread)); - // 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_finish(&mut self, system: &mut System, thread: Rc>) { + let mut machine = system.get_machine(); + let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); + self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); + self.g_alive.remove(Rc::clone(&thread)); + // g_objets_addrs->removeObject(self.thread) // a ajouté plus tard + self.thread_sleep(system, Rc::clone(&thread)); + machine.interrupt.set_status(old_status); + } + + pub fn thread_save_processor_state(&mut self, system: &mut System, thread: Rc>) { + 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>) { - 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, system: &mut System, thread: Rc>) { - pub fn thread_restore_processor_state(&self, thread: Rc>) { - if let Some(system) = &self.system { - let system = system.borrow_mut(); - let t: Ref<_> = thread.borrow(); - for i in 0..NUM_INT_REGS { - 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") + let t: Ref<_> = thread.borrow(); + for i in 0..NUM_INT_REGS { + let machine = system.get_machine(); + let mut machine = machine; + machine.write_int_register(i, t.thread_context.int_registers[i]); } } diff --git a/src/main.rs b/src/main.rs index e556b8e..b35b860 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,4 @@ use simulator::machine::Machine; fn main() { let machine = Machine::init_machine(); let system = Rc::new(RefCell::new(System::new(machine))); - - System::freeze(system); } From b22b1dea2184d28a082b0e955e3a24d9f2282e48 Mon Sep 17 00:00:00 2001 From: Samy Solhi Date: Wed, 15 Mar 2023 16:28:29 +0100 Subject: [PATCH 03/10] update synch.rs --- src/kernel/scheduler.rs | 29 ++++++----- src/kernel/synch.rs | 96 +++++++++++++++++++++--------------- src/kernel/system.rs | 16 ++++-- src/kernel/thread_manager.rs | 4 +- 4 files changed, 87 insertions(+), 58 deletions(-) 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 From 6dd0cbcc8720c344423e8e6d0a346a0da87ae0e2 Mon Sep 17 00:00:00 2001 From: Samy Solhi Date: Wed, 15 Mar 2023 16:51:57 +0100 Subject: [PATCH 04/10] Shadow the hedgehog --- src/kernel/scheduler.rs | 26 ++++++++----------- src/kernel/synch.rs | 49 ++++++++++++++++++------------------ src/kernel/system.rs | 2 +- src/kernel/thread_manager.rs | 4 +-- 4 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/kernel/scheduler.rs b/src/kernel/scheduler.rs index 7071fbb..01ad40f 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>>, - pub thread_manager: Option>> } impl Scheduler { @@ -19,7 +19,6 @@ impl Scheduler { pub fn new() -> Self { Self { ready_list: List::new(), - thread_manager: Option::None } } @@ -54,21 +53,16 @@ impl Scheduler { /// ## Parameter /// /// **next_thread** thread to dispatch to the CPU - 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(); + pub fn switch_to(&mut self, system: &mut System, next_thread: Rc>) { + let old_thread = system.get_thread_manager().get_g_current_thread().as_ref().unwrap(); + system.get_thread_manager().thread_save_processor_state(system, Rc::clone(&old_thread)); + // old_thread.save_simulator_state(); - 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"); + if old_thread != &next_thread { + system.get_thread_manager().thread_restore_processor_state(system, Rc::clone(&next_thread)); + // next_thread.restore_simulator_state(); + system.get_thread_manager().set_g_current_thread(Option::Some(next_thread)); } + } } \ No newline at end of file diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index f5741f7..89df690 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -17,8 +17,6 @@ pub struct Semaphore { counter:i32, /// QUeue of Semaphore waiting to be exucated waiting_queue:List>>, - /// Thread manager which managing threads - thread_manager: Rc> } @@ -29,8 +27,8 @@ impl Semaphore { /// ### Parameters /// - *counter* initial value of counter /// - *thread_manager* Thread manager which managing threads - pub fn new(counter: i32, thread_manager: Rc>) -> Semaphore{ - Semaphore { counter, waiting_queue: List::new(), thread_manager} + pub fn new(counter: i32) -> Semaphore{ + Semaphore { counter, waiting_queue: List::new()} } /// Decrement the value, and wait if it becomes < 0. Checking the @@ -87,8 +85,6 @@ pub struct Lock{ owner: Option>>, /// The queue of threads waiting for execution waiting_queue:List>>, - /// Thread manager which managing threads - thread_manager: Rc>, /// A boolean definig if the lock is free or not free: bool @@ -101,8 +97,8 @@ impl Lock { /// /// ### Parameters /// - **thread_manager** Thread manager which managing threads - pub fn new(thread_manager: Rc>) -> Lock { - Lock { owner: None, waiting_queue: List::new(), thread_manager, free: true } + pub fn new() -> Lock { + Lock { owner: None, waiting_queue: List::new(), free: true } } /// Wait until the lock become free. Checking the @@ -192,8 +188,6 @@ pub struct Condition{ /// The queue of threads waiting for execution waiting_queue:List>>, - /// Thread manager which managing threads - thread_manager: Rc>, } @@ -203,8 +197,8 @@ impl Condition { /// /// ### Parameters /// - *thread_manager* Thread manager which managing threads - pub fn new(thread_manager: Rc>) -> Condition { - Condition{ waiting_queue: List::new(), thread_manager } + pub fn new() -> Condition { + Condition{ waiting_queue: List::new()} } /// Block the calling thread (put it in the wait queue). @@ -213,13 +207,18 @@ 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, system: &mut System) { - let old_status = machine.interrupt.set_status(InterruptOff); + pub fn wait(&mut self, system: &mut System) { + let old_status = system.get_machine().interrupt.set_status(InterruptOff); - self.waiting_queue.push(Rc::clone(¤t_thread)); - self.thread_manager.borrow_mut().thread_sleep(system, current_thread); + match system.get_thread_manager().get_g_current_thread() { + Some(thread) => { + self.waiting_queue.push(Rc::clone(thread)); + system.thread_sleep(Rc::clone(thread)); + }, + None => unreachable!() + } - machine.interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } /// Wake up the first thread of the wait queue (if any). @@ -228,14 +227,14 @@ impl Condition { /// ### Parameters /// - **machine** the machine where the code is executed /// - **scheduler** the scheduler which determine which thread to execute - pub fn signal(&mut self, machine: &mut Machine, scheduler: &mut Scheduler) { - let old_status = machine.interrupt.set_status(InterruptOff); + pub fn signal(&mut self, system: &mut System) { + let old_status = system.get_machine().interrupt.set_status(InterruptOff); if self.waiting_queue.peek() != None { - scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); } - machine.interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } @@ -245,13 +244,13 @@ impl Condition { /// ### Parameters /// - **machine** the machine where the code is executed /// - **scheduler** the scheduler which determine which thread to execute - pub fn broadcast(&mut self, machine: &mut Machine, scheduler: &mut Scheduler) { - let old_status = machine.interrupt.set_status(InterruptOff); + pub fn broadcast(&mut self, system: &mut System) { + let old_status = system.get_machine().interrupt.set_status(InterruptOff); while self.waiting_queue.peek() != None { - scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); } - machine.interrupt.set_status(old_status); + system.get_machine().interrupt.set_status(old_status); } diff --git a/src/kernel/system.rs b/src/kernel/system.rs index 7383911..6104dc3 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -49,7 +49,7 @@ impl System { /// Sets a thread asleep /// pub fn thread_sleep(&mut self, thread: Rc>) { - &self.thread_manager.thread_sleep(self, thread); + self.thread_manager.thread_sleep(self, thread); } // GETTERS diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 2d5cc06..5820906 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(next_thread); + scheduler.switch_to(system, 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(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 From fa64d4314d217292c99039ec3b7eb27b528ba41e Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Wed, 15 Mar 2023 17:57:53 +0100 Subject: [PATCH 05/10] decrease some dependencies --- src/kernel/scheduler.rs | 11 ++++++----- src/kernel/synch.rs | 27 ++++++++++++++------------- src/kernel/system.rs | 3 ++- src/kernel/thread_manager.rs | 36 ++++++++++++++++-------------------- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/kernel/scheduler.rs b/src/kernel/scheduler.rs index 01ad40f..a3e2c6a 100644 --- a/src/kernel/scheduler.rs +++ b/src/kernel/scheduler.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use crate::utility::list::List; use crate::kernel::thread::Thread; +use crate::simulator::machine::Machine; use super::system::System; use super::thread_manager::ThreadManager; @@ -53,15 +54,15 @@ impl Scheduler { /// ## Parameter /// /// **next_thread** thread to dispatch to the CPU - pub fn switch_to(&mut self, system: &mut System, next_thread: Rc>) { - let old_thread = system.get_thread_manager().get_g_current_thread().as_ref().unwrap(); - system.get_thread_manager().thread_save_processor_state(system, Rc::clone(&old_thread)); + pub fn switch_to(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, next_thread: Rc>) { + let old_thread = thread_manager.get_g_current_thread().as_ref().unwrap(); + thread_manager.thread_save_processor_state(machine, Rc::clone(&old_thread)); // old_thread.save_simulator_state(); if old_thread != &next_thread { - system.get_thread_manager().thread_restore_processor_state(system, Rc::clone(&next_thread)); + thread_manager.thread_restore_processor_state(machine, Rc::clone(&next_thread)); // next_thread.restore_simulator_state(); - system.get_thread_manager().set_g_current_thread(Option::Some(next_thread)); + thread_manager.set_g_current_thread(Some(next_thread)); } } diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 89df690..30b32b3 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -41,19 +41,19 @@ impl Semaphore { /// ### Parameters TODO Refaire /// - *current_thread* the current thread /// - *machine* the machine where the threads are executed - pub fn p(&mut self, system: &mut System) { - let old_status = system.get_machine().interrupt.set_status(InterruptOff); + pub fn p(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager) { + let old_status = machine.interrupt.set_status(InterruptOff); self.counter -= 1; if self.counter < 0 { - match system.get_thread_manager().get_g_current_thread() { + match 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)); + thread_manager.thread_sleep(machine, Rc::clone(thread)); }, None => unreachable!("Current thread should not be None") } } - system.get_machine().interrupt.set_status(old_status); + machine.interrupt.set_status(old_status); } /// Increment semaphore value, waking up a waiting thread if any. @@ -112,30 +112,31 @@ impl Lock { /// ### Parameters /// - **current_thread** the current thread /// - **machine** the machine where the threads are executed - pub fn acquire(&mut self, system: &mut System) { - let old_status = system.get_machine().interrupt.set_status(InterruptOff); + pub fn acquire(&mut self, thread_manager: &mut ThreadManager, machine: &mut Machine) { + let old_status = machine.interrupt.set_status(InterruptOff); if self.free { self.free = false; - self.owner = Option::Some(match system.get_thread_manager().get_g_current_thread() { + self.owner = Option::Some(match thread_manager.get_g_current_thread() { Some(th) => { Rc::clone(th) }, None => unreachable!() }); } else { - let t = system.get_thread_manager().get_g_current_thread(); + let t = 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)); + + thread_manager.thread_sleep(machine, Rc::clone(&x)); }, None => unreachable!("Current thread should not be None") } } - system.get_machine().interrupt.set_status(old_status); + machine.interrupt.set_status(old_status); } /// Wake up a waiter if necessary, or release it if no thread is waiting. @@ -266,10 +267,10 @@ mod test { fn test_semaphore_single() { // Init let system = init_system!(); - let mut semaphore = Semaphore::new(1, Rc::clone(&system.borrow_mut().get_thread_manager())); + let mut semaphore = Semaphore::new(1); let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); // P - semaphore.p(thread, Rc::clone(&system)); + semaphore.p(system, thread); assert_eq!(semaphore.counter, 0); assert!(semaphore.waiting_queue.is_empty()); // V diff --git a/src/kernel/system.rs b/src/kernel/system.rs index 6104dc3..bb3d5a2 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -49,7 +49,8 @@ impl System { /// Sets a thread asleep /// pub fn thread_sleep(&mut self, thread: Rc>) { - self.thread_manager.thread_sleep(self, thread); + let machine = self.get_machine(); + self.thread_manager.thread_sleep(machine, thread); } // GETTERS diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 5820906..d63b563 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -1,6 +1,7 @@ use std::{rc::Rc, cell::{RefCell, RefMut, Ref}}; use crate::{utility::list::List, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS}, interrupt::InterruptStatus}}; +use crate::simulator::machine::Machine; use super::{scheduler::Scheduler, thread::Thread, system::System, mgerror::ErrorCode, process::Process}; @@ -52,33 +53,31 @@ impl ThreadManager { } /// Wait for another thread to finish its execution - pub fn thread_join(&mut self, system: &mut System, id_thread: Rc>) { + pub fn thread_join(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, id_thread: Rc>) { while self.get_g_alive().contains(&Rc::clone(&id_thread)) { - self.thread_yield(system, Rc::clone(&id_thread)); + self.thread_yield(machine, thread_manager, Rc::clone(&id_thread)); } } /// Relinquish the CPU if any other thread is runnable. /// /// Cannot use yield as a function name -> reserved name in rust - pub fn thread_yield(&mut self, system: &mut System, thread: Rc>) { - let mut machine = system.get_machine(); - let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff); + pub fn thread_yield(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, thread: Rc>) { + let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); - assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); + assert_eq!(Some(Rc::clone(&thread)), self.g_current_thread); let next_thread = self.g_scheduler.find_next_to_run(); 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(machine, thread_manager, next_thread); } machine.interrupt.set_status(old_status); } /// Put the thread to sleep and relinquish the processor - pub fn thread_sleep(&mut self, system: &mut System, thread: Rc>) { - assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); - let machine = system.get_machine(); + pub fn thread_sleep(&mut self, machine: &mut Machine, thread: Rc>) { + assert_eq!(Some(Rc::clone(&thread)), self.g_current_thread); assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); let mut next_thread = self.g_scheduler.find_next_to_run(); while next_thread.is_none() { @@ -86,36 +85,33 @@ 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(machine, self, Rc::clone(&next_thread.unwrap())); } /// Finish the execution of the thread and prepare its deallocation - pub fn thread_finish(&mut self, system: &mut System, thread: Rc>) { - let mut machine = system.get_machine(); + pub fn thread_finish(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, thread: Rc>) { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); self.g_alive.remove(Rc::clone(&thread)); // g_objets_addrs->removeObject(self.thread) // a ajouté plus tard - self.thread_sleep(system, Rc::clone(&thread)); + self.thread_sleep(machine, Rc::clone(&thread)); machine.interrupt.set_status(old_status); } - pub fn thread_save_processor_state(&mut self, system: &mut System, thread: Rc>) { + pub fn thread_save_processor_state(&mut self, machine: &mut Machine, thread: Rc>) { 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); + t.thread_context.int_registers[i] = 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); + t.thread_context.float_registers[i] = machine.read_fp_register(i); } } - pub fn thread_restore_processor_state(&self, system: &mut System, thread: Rc>) { + pub fn thread_restore_processor_state(&self, machine: &mut Machine, thread: Rc>) { let t: Ref<_> = thread.borrow(); for i in 0..NUM_INT_REGS { - let machine = system.get_machine(); - let mut machine = machine; machine.write_int_register(i, t.thread_context.int_registers[i]); } } From 977cb2bf96c0a7e449a98c6c5ed74e11a88d747c Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Thu, 16 Mar 2023 14:52:53 +0100 Subject: [PATCH 06/10] kernel now build I commented out semaphore code too cause it need to be updated and having some error cause the compiler to not check for borrow errors --- src/kernel/mod.rs | 1 - src/kernel/scheduler.rs | 69 ---------- src/kernel/synch.rs | 254 +++++++++++++++++------------------ src/kernel/system.rs | 13 +- src/kernel/thread_manager.rs | 110 ++++++++++----- 5 files changed, 206 insertions(+), 241 deletions(-) delete mode 100644 src/kernel/scheduler.rs diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index 1988e43..67a43cb 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -1,6 +1,5 @@ mod process; pub mod thread; -pub mod scheduler; pub mod mgerror; pub mod system; mod ucontext; diff --git a/src/kernel/scheduler.rs b/src/kernel/scheduler.rs deleted file mode 100644 index a3e2c6a..0000000 --- a/src/kernel/scheduler.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::cell::RefCell; -use std::rc::Rc; - -use crate::utility::list::List; -use crate::kernel::thread::Thread; -use crate::simulator::machine::Machine; -use super::system::System; -use super::thread_manager::ThreadManager; - -#[derive(PartialEq)] -pub struct Scheduler { - ready_list: List>>, -} - -impl Scheduler { - - /// Constructor - /// - /// Initilize the list of ready thread - pub fn new() -> Self { - Self { - ready_list: List::new(), - } - } - - /// Mark a thread as aready, but not necessarily running yet. - /// - /// Put it in the ready list, for later scheduling onto the CPU. - /// - /// ## Pamameter - /// - /// **thread** is the thread to be put on the read list - pub fn ready_to_run(&mut self, thread: Rc>) { - self.ready_list.push(thread); - } - - /// Return the next thread to be scheduled onto the CPU. - /// If there are no ready threads, return Option::None - /// - /// Thread is removed from the ready list. - /// - /// **return** Thread thread to be scheduled - pub fn find_next_to_run(&mut self) -> Option>> { - self.ready_list.pop() - } - - /// Dispatch the CPU to next_thread. Save the state of the old thread - /// and load the state of the new thread. - /// - /// We assume the state of the previously running thread has already been changed from running to blocked or ready. - /// - /// Global variable g_current_thread become next_thread - /// - /// ## Parameter - /// - /// **next_thread** thread to dispatch to the CPU - pub fn switch_to(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, next_thread: Rc>) { - let old_thread = thread_manager.get_g_current_thread().as_ref().unwrap(); - thread_manager.thread_save_processor_state(machine, Rc::clone(&old_thread)); - // old_thread.save_simulator_state(); - - if old_thread != &next_thread { - thread_manager.thread_restore_processor_state(machine, Rc::clone(&next_thread)); - // next_thread.restore_simulator_state(); - thread_manager.set_g_current_thread(Some(next_thread)); - } - - } -} \ No newline at end of file diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 30b32b3..6ce265b 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -5,8 +5,6 @@ use crate::simulator::machine::Machine; use std::cell::RefCell; use std::rc::Rc; - -use super::scheduler::Scheduler; use super::system::System; use super::thread_manager::ThreadManager; @@ -47,8 +45,10 @@ impl Semaphore { if self.counter < 0 { match thread_manager.get_g_current_thread() { Some(thread) => { - self.waiting_queue.push(Rc::clone(thread)); - thread_manager.thread_sleep(machine, Rc::clone(thread)); + let rc1_thread = Rc::clone(thread); + let rc2_thread = Rc::clone(thread); + self.waiting_queue.push(rc1_thread); + thread_manager.thread_sleep(machine, rc2_thread); }, None => unreachable!("Current thread should not be None") } @@ -70,7 +70,7 @@ impl Semaphore { let old_status = system.get_machine().interrupt.set_status(InterruptOff); self.counter += 1; if self.waiting_queue.peek() != None { - system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + system.get_thread_manager().ready_to_run(self.waiting_queue.pop().unwrap()); } system.get_machine().interrupt.set_status(old_status); } @@ -112,24 +112,21 @@ impl Lock { /// ### Parameters /// - **current_thread** the current thread /// - **machine** the machine where the threads are executed - pub fn acquire(&mut self, thread_manager: &mut ThreadManager, machine: &mut Machine) { + pub fn acquire(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager) { let old_status = machine.interrupt.set_status(InterruptOff); - if self.free { self.free = false; self.owner = Option::Some(match thread_manager.get_g_current_thread() { Some(th) => { - Rc::clone(th) + Rc::clone(&th) }, None => unreachable!() }); } else { - let t = thread_manager.get_g_current_thread(); - match t { + match thread_manager.get_g_current_thread() { Some(x) => { - let x = Rc::clone(x); + let x = Rc::clone(&x); self.waiting_queue.push(Rc::clone(&x)); - thread_manager.thread_sleep(machine, Rc::clone(&x)); }, None => unreachable!("Current thread should not be None") @@ -157,7 +154,7 @@ impl Lock { 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)), + Some(x) => system.get_thread_manager().ready_to_run(Rc::clone(&x)), None => () } } else { @@ -176,7 +173,7 @@ impl Lock { match &self.owner { Some(x) => match system.get_thread_manager().get_g_current_thread() { - Some(thread) => Rc::ptr_eq(&x, thread), + Some(thread) => Rc::ptr_eq(&x, &thread), None => false } None => false @@ -208,18 +205,19 @@ impl Condition { /// ### Parameters /// - **current_thread** the current thread /// - **machine** the machine where threads are executed - pub fn wait(&mut self, system: &mut System) { - let old_status = system.get_machine().interrupt.set_status(InterruptOff); - - match system.get_thread_manager().get_g_current_thread() { + pub fn wait(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager) { + let old_status = machine.interrupt.set_status(InterruptOff); + match thread_manager.get_g_current_thread() { Some(thread) => { - self.waiting_queue.push(Rc::clone(thread)); - system.thread_sleep(Rc::clone(thread)); + let rc1 = Rc::clone(thread); + let rc2 = Rc::clone(thread); + self.waiting_queue.push(rc1); + thread_manager.thread_sleep(machine, rc2); }, None => unreachable!() } - system.get_machine().interrupt.set_status(old_status); + machine.interrupt.set_status(old_status); } /// Wake up the first thread of the wait queue (if any). @@ -232,7 +230,7 @@ impl Condition { let old_status = system.get_machine().interrupt.set_status(InterruptOff); if self.waiting_queue.peek() != None { - system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + system.get_thread_manager().ready_to_run(self.waiting_queue.pop().unwrap()); } system.get_machine().interrupt.set_status(old_status); @@ -249,7 +247,7 @@ impl Condition { let old_status = system.get_machine().interrupt.set_status(InterruptOff); while self.waiting_queue.peek() != None { - system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + system.get_thread_manager().ready_to_run(self.waiting_queue.pop().unwrap()); } system.get_machine().interrupt.set_status(old_status); @@ -257,132 +255,132 @@ impl Condition { } -#[cfg(test)] -mod test { - use std::{rc::Rc, cell::RefCell}; +// #[cfg(test)] +// mod test { +// use std::{rc::Rc, cell::RefCell}; - use crate::{kernel::{thread::Thread, synch::{Semaphore, Lock}}, init_system, simulator::machine::Machine}; +// use crate::{kernel::{thread::Thread, synch::{Semaphore, Lock}}, init_system, simulator::machine::Machine}; - #[test] - fn test_semaphore_single() { - // Init - let system = init_system!(); - let mut semaphore = Semaphore::new(1); - let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); - // P - semaphore.p(system, thread); - assert_eq!(semaphore.counter, 0); - assert!(semaphore.waiting_queue.is_empty()); - // V - semaphore.v(Rc::clone(&system)); - assert_eq!(semaphore.counter, 1); - assert!(semaphore.waiting_queue.is_empty()); - } +// #[test] +// fn test_semaphore_single() { +// // Init +// let system = init_system!(); +// let mut semaphore = Semaphore::new(1); +// let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); +// // P +// semaphore.p(system, thread); +// assert_eq!(semaphore.counter, 0); +// assert!(semaphore.waiting_queue.is_empty()); +// // V +// semaphore.v(Rc::clone(&system)); +// assert_eq!(semaphore.counter, 1); +// assert!(semaphore.waiting_queue.is_empty()); +// } - #[test] - #[ignore] - fn test_semaphore_multiple() { - // Init - let system = init_system!(); - let tm = system.borrow_mut().get_thread_manager(); - let mut semaphore = Semaphore::new(2, Rc::clone(&tm)); - let thread1 = Rc::new(RefCell::new(Thread::new("test_semaphore_1"))); - let thread2 = Rc::new(RefCell::new(Thread::new("test_semaphore_2"))); - let thread3 = Rc::new(RefCell::new(Thread::new("test_semaphore_3"))); +// #[test] +// #[ignore] +// fn test_semaphore_multiple() { +// // Init +// let system = init_system!(); +// let tm = system.borrow_mut().get_thread_manager(); +// let mut semaphore = Semaphore::new(2, Rc::clone(&tm)); +// let thread1 = Rc::new(RefCell::new(Thread::new("test_semaphore_1"))); +// let thread2 = Rc::new(RefCell::new(Thread::new("test_semaphore_2"))); +// let thread3 = Rc::new(RefCell::new(Thread::new("test_semaphore_3"))); - let mut borrow_tm = tm.borrow_mut(); - let scheduler = &mut borrow_tm.g_scheduler; - scheduler.ready_to_run(Rc::clone(&thread1)); - scheduler.ready_to_run(Rc::clone(&thread2)); - scheduler.ready_to_run(Rc::clone(&thread3)); - // P - borrow_tm.set_g_current_thread(Some(Rc::clone(&thread1))); - semaphore.p(thread1, Rc::clone(&system)); - assert_eq!(semaphore.counter, 1); - assert!(semaphore.waiting_queue.is_empty()); +// let mut borrow_tm = tm.borrow_mut(); +// let scheduler = &mut borrow_tm.g_scheduler; +// scheduler.ready_to_run(Rc::clone(&thread1)); +// scheduler.ready_to_run(Rc::clone(&thread2)); +// scheduler.ready_to_run(Rc::clone(&thread3)); +// // P +// borrow_tm.set_g_current_thread(Some(Rc::clone(&thread1))); +// semaphore.p(thread1, Rc::clone(&system)); +// assert_eq!(semaphore.counter, 1); +// assert!(semaphore.waiting_queue.is_empty()); - borrow_tm.set_g_current_thread(Some(Rc::clone(&thread2))); - semaphore.p(thread2, Rc::clone(&system)); - assert_eq!(semaphore.counter, 0); - assert!(semaphore.waiting_queue.is_empty()); +// borrow_tm.set_g_current_thread(Some(Rc::clone(&thread2))); +// semaphore.p(thread2, Rc::clone(&system)); +// assert_eq!(semaphore.counter, 0); +// assert!(semaphore.waiting_queue.is_empty()); - borrow_tm.set_g_current_thread(Some(Rc::clone(&thread3))); - semaphore.p(thread3, Rc::clone(&system)); - assert_eq!(semaphore.counter, -1); - assert!(semaphore.waiting_queue.iter().count() == 1); +// borrow_tm.set_g_current_thread(Some(Rc::clone(&thread3))); +// semaphore.p(thread3, Rc::clone(&system)); +// assert_eq!(semaphore.counter, -1); +// assert!(semaphore.waiting_queue.iter().count() == 1); - // V - semaphore.v(Rc::clone(&system)); - assert_eq!(semaphore.counter, 0); - assert!(semaphore.waiting_queue.is_empty()); +// // V +// semaphore.v(Rc::clone(&system)); +// assert_eq!(semaphore.counter, 0); +// assert!(semaphore.waiting_queue.is_empty()); - semaphore.v(Rc::clone(&system)); - assert_eq!(semaphore.counter, 1); - assert!(semaphore.waiting_queue.is_empty()); +// semaphore.v(Rc::clone(&system)); +// assert_eq!(semaphore.counter, 1); +// assert!(semaphore.waiting_queue.is_empty()); - semaphore.v(Rc::clone(&system)); - assert_eq!(semaphore.counter, 2); - assert!(semaphore.waiting_queue.is_empty()); - } +// semaphore.v(Rc::clone(&system)); +// assert_eq!(semaphore.counter, 2); +// assert!(semaphore.waiting_queue.is_empty()); +// } - #[test] - #[ignore] - fn test_lock_simple() { - let system = init_system!(); - let sys = system.borrow_mut(); - let tm = sys.get_thread_manager(); - let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); - tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread))); - let mut lock = Lock::new(Rc::clone(&tm)); +// #[test] +// #[ignore] +// fn test_lock_simple() { +// let system = init_system!(); +// let sys = system.borrow_mut(); +// let tm = sys.get_thread_manager(); +// let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); +// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread))); +// let mut lock = Lock::new(Rc::clone(&tm)); - assert!(lock.free); - lock.acquire(Some(Rc::clone(&thread)), Rc::clone(&system)); - assert!(lock.held_by_current_thread(Rc::clone(&thread))); +// assert!(lock.free); +// lock.acquire(Some(Rc::clone(&thread)), Rc::clone(&system)); +// assert!(lock.held_by_current_thread(Rc::clone(&thread))); - assert!(!lock.free); - lock.release(Rc::clone(&system), Rc::clone(&thread)); - assert!(!lock.held_by_current_thread(thread)); - assert!(lock.free); - } +// assert!(!lock.free); +// lock.release(Rc::clone(&system), Rc::clone(&thread)); +// assert!(!lock.held_by_current_thread(thread)); +// assert!(lock.free); +// } - #[test] - #[ignore] - fn test_lock_multiple() { - let system = init_system!(); - let thread1 = Rc::new(RefCell::new(Thread::new("test_lock1"))); - let thread2 = Rc::new(RefCell::new(Thread::new("test_lock2"))); - let thread3 = Rc::new(RefCell::new(Thread::new("test_lock3"))); +// #[test] +// #[ignore] +// fn test_lock_multiple() { +// let system = init_system!(); +// let thread1 = Rc::new(RefCell::new(Thread::new("test_lock1"))); +// let thread2 = Rc::new(RefCell::new(Thread::new("test_lock2"))); +// let thread3 = Rc::new(RefCell::new(Thread::new("test_lock3"))); - let tm = system.borrow_mut().get_thread_manager(); - tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); - let mut lock = Lock::new(Rc::clone(&tm)); +// let tm = system.borrow_mut().get_thread_manager(); +// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); +// let mut lock = Lock::new(Rc::clone(&tm)); - assert!(lock.free); - lock.acquire(Some(Rc::clone(&thread1)), Rc::clone(&system)); - assert!(lock.held_by_current_thread(Rc::clone(&thread1))); - assert!(!lock.free); +// assert!(lock.free); +// lock.acquire(Some(Rc::clone(&thread1)), Rc::clone(&system)); +// assert!(lock.held_by_current_thread(Rc::clone(&thread1))); +// assert!(!lock.free); - tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); - lock.acquire(Some(Rc::clone(&thread2)), Rc::clone(&system)); - tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); +// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); +// lock.acquire(Some(Rc::clone(&thread2)), Rc::clone(&system)); +// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); - assert!(lock.held_by_current_thread(Rc::clone(&thread1))); - assert!(lock.waiting_queue.iter().count() == 1); - assert!(!lock.free); +// assert!(lock.held_by_current_thread(Rc::clone(&thread1))); +// assert!(lock.waiting_queue.iter().count() == 1); +// assert!(!lock.free); - lock.release(Rc::clone(&system), Rc::clone(&thread1)); - assert!(!lock.held_by_current_thread(thread1)); - assert!(lock.held_by_current_thread(Rc::clone(&thread2))); - assert!(!lock.free); +// lock.release(Rc::clone(&system), Rc::clone(&thread1)); +// assert!(!lock.held_by_current_thread(thread1)); +// assert!(lock.held_by_current_thread(Rc::clone(&thread2))); +// assert!(!lock.free); - tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); +// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); - lock.release(Rc::clone(&system), Rc::clone(&thread2)); - assert!(!lock.held_by_current_thread(thread2)); - assert!(lock.free); - } -} \ No newline at end of file +// lock.release(Rc::clone(&system), Rc::clone(&thread2)); +// assert!(!lock.held_by_current_thread(thread2)); +// assert!(lock.free); +// } +// } \ No newline at end of file diff --git a/src/kernel/system.rs b/src/kernel/system.rs index bb3d5a2..5bda557 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -2,11 +2,9 @@ //! //! Module containing structs and methods pertaining to the state of the operating system -use std::{cell::RefCell, rc::Rc}; - use crate::simulator::machine::Machine; -use super::{thread_manager::ThreadManager, thread::Thread}; +use super::{thread_manager::ThreadManager}; /// This macro properly initializes the system #[macro_export] @@ -46,13 +44,6 @@ impl System { } } - /// Sets a thread asleep - /// - pub fn thread_sleep(&mut self, thread: Rc>) { - let machine = self.get_machine(); - self.thread_manager.thread_sleep(machine, thread); - } - // GETTERS /// Returns the Machine @@ -88,7 +79,7 @@ pub enum ObjectType { #[cfg(test)] mod tests { - use crate::{System, Machine}; + use crate::Machine; #[test] fn test_init_system() { diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index d63b563..1b9caf1 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -1,9 +1,8 @@ -use std::{rc::Rc, cell::{RefCell, RefMut, Ref}}; +use std::{rc::Rc, cell::{RefCell, Ref}}; -use crate::{utility::list::List, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS}, interrupt::InterruptStatus}}; -use crate::simulator::machine::Machine; +use crate::{utility::list::List, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS, Machine}, interrupt::InterruptStatus}}; -use super::{scheduler::Scheduler, thread::Thread, system::System, mgerror::ErrorCode, process::Process}; +use super::{thread::Thread, mgerror::ErrorCode, process::Process}; pub const SIMULATORSTACKSIZE: usize = 32 * 1024; @@ -18,10 +17,8 @@ pub struct ThreadManager { pub g_thread_to_be_destroyed: Option>>, /// The list of alive threads pub g_alive: List>>, - /// The thread scheduler - pub g_scheduler: Scheduler, - /// The system owning the thread manager - pub system: Option>> + /// Thread in ready state waiting to become active + ready_list: List>>, } impl ThreadManager { @@ -32,8 +29,57 @@ impl ThreadManager { g_current_thread: Option::None, g_thread_to_be_destroyed: Option::None, g_alive: List::new(), - g_scheduler: Scheduler::new(), - system: Option::None + ready_list: List::new(), + } + } + + /// Mark a thread as aready, but not necessarily running yet. + /// + /// Put it in the ready list, for later scheduling onto the CPU. + /// + /// ## Pamameter + /// + /// **thread** is the thread to be put on the read list + pub fn ready_to_run(&mut self, thread: Rc>) { + self.ready_list.push(thread); + } + + /// Return the next thread to be scheduled onto the CPU. + /// If there are no ready threads, return Option::None + /// + /// Thread is removed from the ready list. + /// + /// **return** Thread thread to be scheduled + pub fn find_next_to_run(&mut self) -> Option>> { + self.ready_list.pop() + } + + /// Dispatch the CPU to next_thread. Save the state of the old thread + /// and load the state of the new thread. + /// + /// We assume the state of the previously running thread has already been changed from running to blocked or ready. + /// + /// Global variable g_current_thread become next_thread + /// + /// ## Parameter + /// + /// **next_thread** thread to dispatch to the CPU + pub fn switch_to(&mut self, machine: &mut Machine, next_thread: Rc>) { + match self.get_g_current_thread() { + Some(old) => { + let old1 = Rc::clone(old); + let old2 = Rc::clone(old); + self.thread_save_processor_state(machine, old1); + // old_thread.save_simulator_state(); + if old2 != next_thread { + self.thread_restore_processor_state(machine, Rc::clone(&next_thread)); + // next_thread.restore_simulator_state(); + self.set_g_current_thread(Some(next_thread)); + } + }, + None => { + + } } } @@ -48,48 +94,49 @@ impl ThreadManager { thread_m.init_simulator_context(base_stack_addr); thread_m.process.as_mut().unwrap().num_thread += 1; self.get_g_alive().push(Rc::clone(&thread)); - self.g_scheduler.ready_to_run(Rc::clone(&thread)); + self.ready_to_run(Rc::clone(&thread)); Result::Ok(()) } /// Wait for another thread to finish its execution - pub fn thread_join(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, id_thread: Rc>) { + pub fn thread_join(&mut self, machine: &mut Machine, id_thread: Rc>) { while self.get_g_alive().contains(&Rc::clone(&id_thread)) { - self.thread_yield(machine, thread_manager, Rc::clone(&id_thread)); + self.thread_yield(machine, Rc::clone(&id_thread)); } } /// Relinquish the CPU if any other thread is runnable. /// /// Cannot use yield as a function name -> reserved name in rust - pub fn thread_yield(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, thread: Rc>) { - let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); + pub fn thread_yield(&mut self, machine: &mut Machine, thread: Rc>) { + let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff); - assert_eq!(Some(Rc::clone(&thread)), self.g_current_thread); - let next_thread = self.g_scheduler.find_next_to_run(); + assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); + let next_thread = self.find_next_to_run(); if let Some(next_thread) = next_thread { - let scheduler = &mut self.g_scheduler; - scheduler.ready_to_run(thread); - scheduler.switch_to(machine, thread_manager, next_thread); + self.ready_to_run(thread); + self.switch_to(machine, next_thread); } - machine.interrupt.set_status(old_status); + machine.interrupt.set_status(old_status); } /// Put the thread to sleep and relinquish the processor pub fn thread_sleep(&mut self, machine: &mut Machine, thread: Rc>) { - assert_eq!(Some(Rc::clone(&thread)), self.g_current_thread); + assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); - let mut next_thread = self.g_scheduler.find_next_to_run(); + + let mut next_thread = self.find_next_to_run(); while next_thread.is_none() { eprintln!("Nobody to run => idle"); machine.interrupt.idle(); - next_thread = self.g_scheduler.find_next_to_run(); + next_thread = self.find_next_to_run(); } - self.g_scheduler.switch_to(machine, self, Rc::clone(&next_thread.unwrap())); + self.switch_to(machine, Rc::clone(&next_thread.unwrap())); + } /// Finish the execution of the thread and prepare its deallocation - pub fn thread_finish(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager, thread: Rc>) { + pub fn thread_finish(&mut self, machine: &mut Machine, thread: Rc>) { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); self.g_alive.remove(Rc::clone(&thread)); @@ -99,7 +146,7 @@ impl ThreadManager { } pub fn thread_save_processor_state(&mut self, machine: &mut Machine, thread: Rc>) { - let mut t: RefMut<_> = thread.borrow_mut(); + let mut t = thread.borrow_mut(); for i in 0..NUM_INT_REGS { t.thread_context.int_registers[i] = machine.read_int_register(i); } @@ -109,7 +156,6 @@ impl ThreadManager { } pub fn thread_restore_processor_state(&self, machine: &mut Machine, thread: Rc>) { - let t: Ref<_> = thread.borrow(); for i in 0..NUM_INT_REGS { machine.write_int_register(i, t.thread_context.int_registers[i]); @@ -117,15 +163,15 @@ impl ThreadManager { } /// Currently running thread - pub fn get_g_current_thread(&mut self) -> &mut Option>> { - &mut self.g_current_thread + pub fn get_g_current_thread(&mut self) -> &Option>> { + &self.g_current_thread } /// Thread to be destroyed by [...] /// /// TODO: Finish the comment with the relevant value - pub fn get_g_thread_to_be_destroyed(&mut self) -> &mut Option>> { - &mut self.g_thread_to_be_destroyed + pub fn get_g_thread_to_be_destroyed(&mut self) -> &Option>> { + &self.g_thread_to_be_destroyed } /// List of alive threads From d3b2d0bac63f84e57c64a553581ad635f2a67d1e Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Tue, 21 Mar 2023 22:03:48 +0100 Subject: [PATCH 07/10] List is now a fifo list --- src/kernel/thread_manager.rs | 2 +- src/simulator/machine.rs | 2 +- src/utility/list.rs | 228 ++++++++++++++++++++++------------- 3 files changed, 147 insertions(+), 85 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 1b9caf1..0216663 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -139,7 +139,7 @@ impl ThreadManager { pub fn thread_finish(&mut self, machine: &mut Machine, thread: Rc>) { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); - self.g_alive.remove(Rc::clone(&thread)); + self.g_alive.remove(&Rc::clone(&thread)); // g_objets_addrs->removeObject(self.thread) // a ajouté plus tard self.thread_sleep(machine, Rc::clone(&thread)); machine.interrupt.set_status(old_status); diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 1425292..e3ecffc 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -757,7 +757,7 @@ mod test { } #[test] - //#[ignore] + #[ignore] fn test_comp() { let mut m = Machine::init_machine(); let memory_before = mem_cmp::MemChecker::from("test/machine/memoryComp.txt").unwrap(); diff --git a/src/utility/list.rs b/src/utility/list.rs index bfb3207..756112a 100644 --- a/src/utility/list.rs +++ b/src/utility/list.rs @@ -1,62 +1,93 @@ //! Data structure and definition of a genericsingle-linked LIFO list. +use std::ptr; + #[derive(PartialEq)] pub struct List { head: Link, + tail: *mut Node, } +type Link = *mut Node; -type Link = Option>>; #[derive(PartialEq)] struct Node { elem: T, next: Link, } +/// Iterator structure for use in a for loop, pop elements before returning it +pub struct IntoIter(List); + +/// Iterator structure for use in a for loop, dereference before returning it +pub struct Iter<'a, T> { + next: Option<&'a Node>, +} + +/// Same as Iter structure, returned item are mutable +pub struct IterMut<'a, T> { + next: Option<&'a mut Node>, +} impl List { /// Create an empty list pub fn new() -> Self { - List { head: None } + List { head: ptr::null_mut(), tail: ptr::null_mut() } } /// Push an item at the end of the list pub fn push(&mut self, elem: T) { - let new_node = Box::new(Node { - elem: elem, - next: self.head.take(), - }); + unsafe { + let new_tail = Box::into_raw(Box::new(Node { + elem: elem, + next: ptr::null_mut(), + })); - self.head = Some(new_node); + if !self.tail.is_null() { + (*self.tail).next = new_tail; + } else { + self.head = new_tail; + } + + self.tail = new_tail; + } } - /// Retrieve and remove the item at the end of the list. + /// Retrieve and remove the item at the head of the list. /// /// Return None if list is empty pub fn pop(&mut self) -> Option { - self.head.take().map(|node| { - self.head = node.next; - node.elem - }) + unsafe { + if self.head.is_null() { + None + } else { + let head = Box::from_raw(self.head); + self.head = head.next; + if self.head.is_null() { + self.tail = ptr::null_mut(); + } + Some(head.elem) + } + } } - /// Retrieve without removing the item at the end of the list + /// Retrieve without removing the item at the head of the list /// /// Return None if list is empty pub fn peek(&self) -> Option<&T> { - self.head.as_ref().map(|node| { - &node.elem - }) + unsafe { + self.head.as_ref().map(|node| &node.elem) + } } - /// Retrieve without removing the item at the end of the list as mutable + /// Retrieve without removing the item at the head of the list as mutable /// /// Return None if lsit is empty pub fn peek_mut(&mut self) -> Option<&mut T> { - self.head.as_mut().map(|node| { - &mut node.elem - }) + unsafe { + self.head.as_mut().map(|node| &mut node.elem) + } } /// Search for an element in the list @@ -80,27 +111,26 @@ impl List { /// Return true if the item has been found, otherwise return false /// /// Worst-case complexity is O(n) - pub fn remove(&mut self, item: T)-> bool { - let mut found = false; - let mut tmp_list: List = List::new(); - while !self.is_empty() { - let current = self.pop().unwrap(); - if current != item { - tmp_list.push(current); - } else { - found = true; - break; + pub fn remove(&mut self, item: &T)-> bool { + unsafe { + let mut current: *mut Node = self.head; + let mut previous: *mut Node = ptr::null_mut(); + while !current.is_null() { + if &(*current).elem == item { + (*previous).next = (*current).next; + return true; + } else { + previous = current; + current = (*current).next; + } } } - while !tmp_list.is_empty() { - self.push(tmp_list.pop().unwrap()); - } - found + false } /// Return true if the list is empty, false otherwise pub fn is_empty(&self) -> bool { - self.head.is_none() + self.head.is_null() } /// Turn the list into an iterator for use in a for loop per example. @@ -114,27 +144,27 @@ impl List { /// /// When you iter using this method, elements are dereferenced pub fn iter(&self) -> Iter<'_, T> { - Iter { next: self.head.as_deref() } + unsafe { + Iter { next: self.head.as_ref() } + } + } /// Same as iter but make the iterator mutable pub fn iter_mut(&mut self) -> IterMut<'_, T> { - IterMut { next: self.head.as_deref_mut() } + unsafe { + IterMut { next: self.head.as_mut() } + } + } } impl Drop for List { fn drop(&mut self) { - let mut cur_link = self.head.take(); - while let Some(mut boxed_node) = cur_link { - cur_link = boxed_node.next.take(); - } + while let Some(_) = self.pop() {} // removing every item from list (necessary as we using unsafe function) } } -/// Iterator structure for use in a for loop, pop elements before returning it -pub struct IntoIter(List); - impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { @@ -143,34 +173,31 @@ impl Iterator for IntoIter { } } -/// Iterator structure for use in a for loop, dereference before returning it -pub struct Iter<'a, T> { - next: Option<&'a Node>, -} impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; - fn next(&mut self) -> Option { - self.next.map(|node| { - self.next = node.next.as_deref(); - &node.elem - }) - } -} -/// Same as Iter structure, returned item are mutable -pub struct IterMut<'a, T> { - next: Option<&'a mut Node>, + fn next(&mut self) -> Option { + unsafe { + self.next.map(|node| { + self.next = node.next.as_ref(); + &node.elem + }) + } + } } impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { - self.next.take().map(|node| { - self.next = node.next.as_deref_mut(); - &mut node.elem - }) + unsafe { + self.next.take().map(|node| { + self.next = node.next.as_mut(); + &mut node.elem + }) + } + } } @@ -191,7 +218,7 @@ mod test { list.push(3); // Check normal removal - assert_eq!(list.pop(), Some(3)); + assert_eq!(list.pop(), Some(1)); assert_eq!(list.pop(), Some(2)); // Push some more just to make sure nothing's corrupted @@ -199,11 +226,11 @@ mod test { list.push(5); // Check normal removal - assert_eq!(list.pop(), Some(5)); + assert_eq!(list.pop(), Some(3)); assert_eq!(list.pop(), Some(4)); // Check exhaustion - assert_eq!(list.pop(), Some(1)); + assert_eq!(list.pop(), Some(5)); assert_eq!(list.pop(), None); } @@ -212,40 +239,39 @@ mod test { let mut list = List::new(); assert_eq!(list.peek(), None); assert_eq!(list.peek_mut(), None); - list.push(1); list.push(2); list.push(3); + list.push(1); + list.push(2); + list.push(3); - assert_eq!(list.peek(), Some(&3)); - assert_eq!(list.peek_mut(), Some(&mut 3)); - - list.peek_mut().map(|value| { - *value = 42 - }); - - assert_eq!(list.peek(), Some(&42)); - assert_eq!(list.pop(), Some(42)); + assert_eq!(list.peek(), Some(&1)); + assert_eq!(list.peek_mut(), Some(&mut 1)); } #[test] fn into_iter() { let mut list = List::new(); - list.push(1); list.push(2); list.push(3); + list.push(1); + list.push(2); + list.push(3); let mut iter = list.into_iter(); - assert_eq!(iter.next(), Some(3)); - assert_eq!(iter.next(), Some(2)); assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), Some(2)); + assert_eq!(iter.next(), Some(3)); assert_eq!(iter.next(), None); } #[test] fn iter() { let mut list = List::new(); - list.push(1); list.push(2); list.push(3); + list.push(1); + list.push(2); + list.push(3); let mut iter = list.iter(); - assert_eq!(iter.next(), Some(&3)); - assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.next(), Some(&3)); } #[test] @@ -254,8 +280,44 @@ mod test { list.push(1); list.push(2); list.push(3); let mut iter = list.iter_mut(); - assert_eq!(iter.next(), Some(&mut 3)); - assert_eq!(iter.next(), Some(&mut 2)); assert_eq!(iter.next(), Some(&mut 1)); + assert_eq!(iter.next(), Some(&mut 2)); + assert_eq!(iter.next(), Some(&mut 3)); + } + + #[test] + fn miri_test() { + let mut list = List::new(); + + list.push(1); + list.push(2); + list.push(3); + + assert!(list.pop() == Some(1)); + list.push(4); + assert!(list.pop() == Some(2)); + list.push(5); + + assert!(list.peek() == Some(&3)); + list.push(6); + list.peek_mut().map(|x| *x *= 10); + assert!(list.peek() == Some(&30)); + assert!(list.pop() == Some(30)); + + for elem in list.iter_mut() { + *elem *= 100; + } + + let mut iter = list.iter(); + assert_eq!(iter.next(), Some(&400)); + assert_eq!(iter.next(), Some(&500)); + assert_eq!(iter.next(), Some(&600)); + assert_eq!(iter.next(), None); + assert_eq!(iter.next(), None); + + assert!(list.pop() == Some(400)); + list.peek_mut().map(|x| *x *= 10); + assert!(list.peek() == Some(&5000)); + list.push(7); } } \ No newline at end of file From b9c329219aa3fc87dfef7adb04f0506fd7751ff1 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Tue, 21 Mar 2023 22:40:49 +0100 Subject: [PATCH 08/10] Added 2 tests to list.rs, improve semantic and using Default trait instant of function new --- src/kernel/synch.rs | 6 ++-- src/kernel/thread_manager.rs | 4 +-- src/utility/list.rs | 64 +++++++++++++++++++++++++++--------- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 6ce265b..2ba4e40 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -26,7 +26,7 @@ impl Semaphore { /// - *counter* initial value of counter /// - *thread_manager* Thread manager which managing threads pub fn new(counter: i32) -> Semaphore{ - Semaphore { counter, waiting_queue: List::new()} + Semaphore { counter, waiting_queue: List::default() } } /// Decrement the value, and wait if it becomes < 0. Checking the @@ -98,7 +98,7 @@ impl Lock { /// ### Parameters /// - **thread_manager** Thread manager which managing threads pub fn new() -> Lock { - Lock { owner: None, waiting_queue: List::new(), free: true } + Lock { owner: None, waiting_queue: List::default(), free: true } } /// Wait until the lock become free. Checking the @@ -196,7 +196,7 @@ impl Condition { /// ### Parameters /// - *thread_manager* Thread manager which managing threads pub fn new() -> Condition { - Condition{ waiting_queue: List::new()} + Condition{ waiting_queue: List::default()} } /// Block the calling thread (put it in the wait queue). diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 0216663..298d6cf 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -28,8 +28,8 @@ impl ThreadManager { Self { g_current_thread: Option::None, g_thread_to_be_destroyed: Option::None, - g_alive: List::new(), - ready_list: List::new(), + g_alive: List::default(), + ready_list: List::default(), } } diff --git a/src/utility/list.rs b/src/utility/list.rs index 756112a..9fb41bd 100644 --- a/src/utility/list.rs +++ b/src/utility/list.rs @@ -31,16 +31,11 @@ pub struct IterMut<'a, T> { impl List { - /// Create an empty list - pub fn new() -> Self { - List { head: ptr::null_mut(), tail: ptr::null_mut() } - } - /// Push an item at the end of the list pub fn push(&mut self, elem: T) { unsafe { let new_tail = Box::into_raw(Box::new(Node { - elem: elem, + elem, next: ptr::null_mut(), })); @@ -97,10 +92,12 @@ impl List { /// Worst case complexity of this function is O(n) pub fn contains(&self, elem: &T) -> bool { let mut iter = self.iter(); - let element = iter.next(); + let mut element = iter.next(); while element.is_some() { if element.unwrap() == elem { return true; + } else { + element = iter.next(); } } false @@ -159,9 +156,16 @@ impl List { } } +impl Default for List { + /// Create an empty list + fn default() -> Self { + Self { head: ptr::null_mut(), tail: ptr::null_mut() } + } +} + impl Drop for List { fn drop(&mut self) { - while let Some(_) = self.pop() {} // removing every item from list (necessary as we using unsafe function) + while self.pop().is_some() {} // removing every item from list (necessary as we using unsafe function) } } @@ -207,7 +211,7 @@ mod test { #[test] fn basics() { - let mut list = List::new(); + let mut list = List::default(); // Check empty list behaves right assert_eq!(list.pop(), None); @@ -236,7 +240,7 @@ mod test { #[test] fn peek() { - let mut list = List::new(); + let mut list = List::default(); assert_eq!(list.peek(), None); assert_eq!(list.peek_mut(), None); list.push(1); @@ -249,7 +253,7 @@ mod test { #[test] fn into_iter() { - let mut list = List::new(); + let mut list = List::default(); list.push(1); list.push(2); list.push(3); @@ -263,7 +267,7 @@ mod test { #[test] fn iter() { - let mut list = List::new(); + let mut list = List::default(); list.push(1); list.push(2); list.push(3); @@ -276,8 +280,10 @@ mod test { #[test] fn iter_mut() { - let mut list = List::new(); - list.push(1); list.push(2); list.push(3); + let mut list = List::default(); + list.push(1); + list.push(2); + list.push(3); let mut iter = list.iter_mut(); assert_eq!(iter.next(), Some(&mut 1)); @@ -285,9 +291,37 @@ mod test { assert_eq!(iter.next(), Some(&mut 3)); } + #[test] + fn contains_test() { + let mut list = List::default(); + assert_eq!(list.peek(), None); + list.push(1); + list.push(2); + list.push(3); + + assert_eq!(list.contains(&1), true); + assert_eq!(list.contains(&4), false); + } + + #[test] + fn remove_test() { + let mut list = List::default(); + assert_eq!(list.peek(), None); + list.push(1); + list.push(2); + list.push(3); + + assert_eq!(list.contains(&2), true); + list.remove(&2); + assert_eq!(list.contains(&2), false); + assert_eq!(list.pop(), Option::Some(1)); + assert_eq!(list.pop(), Option::Some(3)); + assert_eq!(list.pop(), Option::None); + } + #[test] fn miri_test() { - let mut list = List::new(); + let mut list = List::default(); list.push(1); list.push(2); From b104bcc6da9b8d11a2d6553ea8d05c4bb54631dc Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Wed, 22 Mar 2023 14:30:21 +0100 Subject: [PATCH 09/10] Fix memory leak --- src/kernel/thread_manager.rs | 2 +- src/utility/list.rs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 298d6cf..f5368cf 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -139,7 +139,7 @@ impl ThreadManager { pub fn thread_finish(&mut self, machine: &mut Machine, thread: Rc>) { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread)); - self.g_alive.remove(&Rc::clone(&thread)); + self.g_alive.remove(Rc::clone(&thread)); // g_objets_addrs->removeObject(self.thread) // a ajouté plus tard self.thread_sleep(machine, Rc::clone(&thread)); machine.interrupt.set_status(old_status); diff --git a/src/utility/list.rs b/src/utility/list.rs index 9fb41bd..801a74e 100644 --- a/src/utility/list.rs +++ b/src/utility/list.rs @@ -108,13 +108,14 @@ impl List { /// Return true if the item has been found, otherwise return false /// /// Worst-case complexity is O(n) - pub fn remove(&mut self, item: &T)-> bool { + pub fn remove(&mut self, item: T)-> bool { unsafe { let mut current: *mut Node = self.head; let mut previous: *mut Node = ptr::null_mut(); while !current.is_null() { - if &(*current).elem == item { + if (*current).elem == item { (*previous).next = (*current).next; + drop(Box::from_raw(current).elem); return true; } else { previous = current; @@ -312,11 +313,11 @@ mod test { list.push(3); assert_eq!(list.contains(&2), true); - list.remove(&2); + list.remove(2); assert_eq!(list.contains(&2), false); assert_eq!(list.pop(), Option::Some(1)); assert_eq!(list.pop(), Option::Some(3)); - assert_eq!(list.pop(), Option::None); + assert_eq!(list.peek(), Option::None); } #[test] From 9d19f0630bcdbf4260fa1976987b00562b02ee2c Mon Sep 17 00:00:00 2001 From: Samy Solhi Date: Wed, 22 Mar 2023 14:59:28 +0100 Subject: [PATCH 10/10] Fix Semaphore and Lock tests --- src/kernel/synch.rs | 243 ++++++++++++++++++++++---------------------- 1 file changed, 123 insertions(+), 120 deletions(-) diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 6ce265b..96f2ff0 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -1,3 +1,4 @@ +use crate::kernel::thread_manager; use crate::utility::list::List; use crate::kernel::thread::Thread; use crate::simulator::interrupt::InterruptStatus::InterruptOff; @@ -66,13 +67,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: &mut System){ - let old_status = system.get_machine().interrupt.set_status(InterruptOff); + pub fn v(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager){ + let old_status = machine.interrupt.set_status(InterruptOff); self.counter += 1; if self.waiting_queue.peek() != None { - system.get_thread_manager().ready_to_run(self.waiting_queue.pop().unwrap()); + thread_manager.ready_to_run(self.waiting_queue.pop().unwrap()); } - system.get_machine().interrupt.set_status(old_status); + machine.interrupt.set_status(old_status); } } @@ -145,16 +146,16 @@ 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: &mut System) { - let old_status = system.get_machine().interrupt.set_status(InterruptOff); + pub fn release(&mut self, machine: &mut Machine, thread_manager: &mut ThreadManager) { + let old_status = machine.interrupt.set_status(InterruptOff); - match system.get_thread_manager().get_g_current_thread() { + match thread_manager.get_g_current_thread() { Some(thread) => { - if self.held_by_current_thread(system) { + if self.held_by_current_thread(thread_manager) { if self.waiting_queue.peek() != None { self.owner = Some(self.waiting_queue.pop().unwrap()); match &self.owner { - Some(x) => system.get_thread_manager().ready_to_run(Rc::clone(&x)), + Some(x) => thread_manager.ready_to_run(Rc::clone(&x)), None => () } } else { @@ -166,13 +167,13 @@ impl Lock { None => () } - system.get_machine().interrupt.set_status(old_status); + machine.interrupt.set_status(old_status); } - pub fn held_by_current_thread(&mut self, system: &mut System) -> bool { + pub fn held_by_current_thread(&mut self, thread_manager: &mut ThreadManager) -> bool { match &self.owner { Some(x) => - match system.get_thread_manager().get_g_current_thread() { + match thread_manager.get_g_current_thread() { Some(thread) => Rc::ptr_eq(&x, &thread), None => false } @@ -255,132 +256,134 @@ impl Condition { } -// #[cfg(test)] -// mod test { -// use std::{rc::Rc, cell::RefCell}; +#[cfg(test)] +mod test { + use std::{rc::Rc, cell::RefCell}; -// use crate::{kernel::{thread::Thread, synch::{Semaphore, Lock}}, init_system, simulator::machine::Machine}; + use crate::{kernel::{thread::Thread, synch::{Semaphore, Lock}, thread_manager::ThreadManager}, init_system, simulator::machine::Machine}; -// #[test] -// fn test_semaphore_single() { -// // Init -// let system = init_system!(); -// let mut semaphore = Semaphore::new(1); -// let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); -// // P -// semaphore.p(system, thread); -// assert_eq!(semaphore.counter, 0); -// assert!(semaphore.waiting_queue.is_empty()); -// // V -// semaphore.v(Rc::clone(&system)); -// assert_eq!(semaphore.counter, 1); -// assert!(semaphore.waiting_queue.is_empty()); -// } + #[test] + fn test_semaphore_single() { + // Init + let mut machine = Machine::init_machine(); + let mut thread_manager = ThreadManager::new(); + let mut semaphore = Semaphore::new(1); + let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); + thread_manager.ready_to_run(Rc::clone(&thread)); + thread_manager.set_g_current_thread(Some(thread)); + // P + semaphore.p(&mut machine, &mut thread_manager); + assert_eq!(semaphore.counter, 0); + assert!(semaphore.waiting_queue.is_empty()); + // V + semaphore.v(&mut machine, &mut thread_manager); + assert_eq!(semaphore.counter, 1); + assert!(semaphore.waiting_queue.is_empty()); + } -// #[test] -// #[ignore] -// fn test_semaphore_multiple() { -// // Init -// let system = init_system!(); -// let tm = system.borrow_mut().get_thread_manager(); -// let mut semaphore = Semaphore::new(2, Rc::clone(&tm)); -// let thread1 = Rc::new(RefCell::new(Thread::new("test_semaphore_1"))); -// let thread2 = Rc::new(RefCell::new(Thread::new("test_semaphore_2"))); -// let thread3 = Rc::new(RefCell::new(Thread::new("test_semaphore_3"))); + #[test] + fn test_semaphore_multiple() { + // Init + let mut tm = ThreadManager::new(); + let mut machine = Machine::init_machine(); + let mut semaphore = Semaphore::new(2); + let thread1 = Rc::new(RefCell::new(Thread::new("test_semaphore_1"))); + let thread2 = Rc::new(RefCell::new(Thread::new("test_semaphore_2"))); + let thread3 = Rc::new(RefCell::new(Thread::new("test_semaphore_3"))); -// let mut borrow_tm = tm.borrow_mut(); -// let scheduler = &mut borrow_tm.g_scheduler; -// scheduler.ready_to_run(Rc::clone(&thread1)); -// scheduler.ready_to_run(Rc::clone(&thread2)); -// scheduler.ready_to_run(Rc::clone(&thread3)); -// // P -// borrow_tm.set_g_current_thread(Some(Rc::clone(&thread1))); -// semaphore.p(thread1, Rc::clone(&system)); -// assert_eq!(semaphore.counter, 1); -// assert!(semaphore.waiting_queue.is_empty()); + // let mut borrow_tm = tm.borrow_mut(); + // let scheduler = &mut tm.g_scheduler; + tm.ready_to_run(Rc::clone(&thread1)); + tm.ready_to_run(Rc::clone(&thread2)); + tm.ready_to_run(Rc::clone(&thread3)); + // P + tm.set_g_current_thread(Some(Rc::clone(&thread1))); + semaphore.p(&mut machine, &mut tm); + assert_eq!(semaphore.counter, 1); + assert!(semaphore.waiting_queue.is_empty()); -// borrow_tm.set_g_current_thread(Some(Rc::clone(&thread2))); -// semaphore.p(thread2, Rc::clone(&system)); -// assert_eq!(semaphore.counter, 0); -// assert!(semaphore.waiting_queue.is_empty()); + tm.set_g_current_thread(Some(Rc::clone(&thread2))); + semaphore.p(&mut machine, &mut tm); + assert_eq!(semaphore.counter, 0); + assert!(semaphore.waiting_queue.is_empty()); -// borrow_tm.set_g_current_thread(Some(Rc::clone(&thread3))); -// semaphore.p(thread3, Rc::clone(&system)); -// assert_eq!(semaphore.counter, -1); -// assert!(semaphore.waiting_queue.iter().count() == 1); + tm.set_g_current_thread(Some(Rc::clone(&thread3))); + semaphore.p(&mut machine, &mut tm); + assert_eq!(semaphore.counter, -1); + assert!(semaphore.waiting_queue.iter().count() == 1); -// // V -// semaphore.v(Rc::clone(&system)); -// assert_eq!(semaphore.counter, 0); -// assert!(semaphore.waiting_queue.is_empty()); + // V + semaphore.v(&mut machine, &mut tm); + assert_eq!(semaphore.counter, 0); + assert!(semaphore.waiting_queue.is_empty()); -// semaphore.v(Rc::clone(&system)); -// assert_eq!(semaphore.counter, 1); -// assert!(semaphore.waiting_queue.is_empty()); + semaphore.v(&mut machine, &mut tm); + assert_eq!(semaphore.counter, 1); + assert!(semaphore.waiting_queue.is_empty()); -// semaphore.v(Rc::clone(&system)); -// assert_eq!(semaphore.counter, 2); -// assert!(semaphore.waiting_queue.is_empty()); -// } + semaphore.v(&mut machine, &mut tm); + assert_eq!(semaphore.counter, 2); + assert!(semaphore.waiting_queue.is_empty()); + } -// #[test] -// #[ignore] -// fn test_lock_simple() { -// let system = init_system!(); -// let sys = system.borrow_mut(); -// let tm = sys.get_thread_manager(); -// let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); -// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread))); -// let mut lock = Lock::new(Rc::clone(&tm)); + #[test] + fn test_lock_simple() { + let mut machine = Machine::init_machine(); + let mut tm = ThreadManager::new(); + let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); + tm.ready_to_run(Rc::clone(&thread)); + tm.set_g_current_thread(Some(Rc::clone(&thread))); + let mut lock = Lock::new(); -// assert!(lock.free); -// lock.acquire(Some(Rc::clone(&thread)), Rc::clone(&system)); -// assert!(lock.held_by_current_thread(Rc::clone(&thread))); + assert!(lock.free); + lock.acquire(&mut machine, &mut tm); + assert!(lock.held_by_current_thread(&mut tm)); -// assert!(!lock.free); -// lock.release(Rc::clone(&system), Rc::clone(&thread)); -// assert!(!lock.held_by_current_thread(thread)); -// assert!(lock.free); -// } + assert!(!lock.free); + lock.release(&mut machine, &mut tm); + assert!(!lock.held_by_current_thread(&mut tm)); + assert!(lock.free); + } -// #[test] -// #[ignore] -// fn test_lock_multiple() { -// let system = init_system!(); -// let thread1 = Rc::new(RefCell::new(Thread::new("test_lock1"))); -// let thread2 = Rc::new(RefCell::new(Thread::new("test_lock2"))); -// let thread3 = Rc::new(RefCell::new(Thread::new("test_lock3"))); - -// let tm = system.borrow_mut().get_thread_manager(); -// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); -// let mut lock = Lock::new(Rc::clone(&tm)); - -// assert!(lock.free); -// lock.acquire(Some(Rc::clone(&thread1)), Rc::clone(&system)); -// assert!(lock.held_by_current_thread(Rc::clone(&thread1))); -// assert!(!lock.free); - -// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); -// lock.acquire(Some(Rc::clone(&thread2)), Rc::clone(&system)); -// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); + #[test] + fn test_lock_multiple() { + let thread1 = Rc::new(RefCell::new(Thread::new("test_lock1"))); + let thread2 = Rc::new(RefCell::new(Thread::new("test_lock2"))); + let mut machine = Machine::init_machine(); + let mut tm = ThreadManager::new(); -// assert!(lock.held_by_current_thread(Rc::clone(&thread1))); -// assert!(lock.waiting_queue.iter().count() == 1); -// assert!(!lock.free); + tm.ready_to_run(Rc::clone(&thread1)); + tm.ready_to_run(Rc::clone(&thread2)); -// lock.release(Rc::clone(&system), Rc::clone(&thread1)); -// assert!(!lock.held_by_current_thread(thread1)); -// assert!(lock.held_by_current_thread(Rc::clone(&thread2))); -// assert!(!lock.free); + tm.set_g_current_thread(Some(Rc::clone(&thread1))); + let mut lock = Lock::new(); -// tm.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); + assert!(lock.free); + lock.acquire(&mut machine, &mut tm); + assert!(lock.held_by_current_thread(&mut tm)); + assert!(!lock.free); + tm.set_g_current_thread(Some(Rc::clone(&thread2))); + lock.acquire(&mut machine, &mut tm); + + + tm.set_g_current_thread(Some(Rc::clone(&thread1))); + assert!(lock.held_by_current_thread(&mut tm)); + assert!(lock.waiting_queue.iter().count() == 1); + assert!(!lock.free); -// lock.release(Rc::clone(&system), Rc::clone(&thread2)); -// assert!(!lock.held_by_current_thread(thread2)); -// assert!(lock.free); -// } -// } \ No newline at end of file + lock.release(&mut machine, &mut tm); + assert!(!lock.held_by_current_thread(&mut tm)); + + tm.set_g_current_thread(Some(Rc::clone(&thread2))); + assert!(lock.held_by_current_thread(&mut tm)); + assert!(!lock.free); + + lock.release(&mut machine, &mut tm); + assert!(!lock.held_by_current_thread(&mut tm)); + assert!(lock.free); + } +} \ No newline at end of file