diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index e7b9ac2..d7257be 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -1,3 +1,4 @@ +use core::panicking::panic; use crate::utility::list::List; use crate::kernel::thread::Thread; use crate::simulator::interrupt::InterruptStatus::InterruptOff; @@ -23,6 +24,10 @@ pub struct Semaphore { impl Semaphore { + pub fn new(counter: i32, thread_manager: Rc>) -> Semaphore{ + Semaphore { counter, waiting_queue: List::new(), thread_manager} + } + /// Decrement the value, and wait if it becomes < 0. Checking the /// value and decrementing must be done atomically, so we /// need to disable interrupts before checking the value. @@ -69,7 +74,7 @@ impl Semaphore { pub struct Lock{ /// Thread owning the lock - owner: Rc>, + owner: Option>>, /// The queue of threads waiting for execution waiting_queue:List>>, /// Thread manager which managing threads @@ -81,6 +86,15 @@ pub struct Lock{ impl Lock { + /// Initialize a Lock, so that it can be used for synchronization. + /// The lock is initialy free + /// + /// ### 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 } + } + /// Wait until the lock become free. Checking the /// state of the lock (free or busy) and modify it must be done /// atomically, so we need to disable interrupts before checking @@ -92,15 +106,20 @@ impl Lock { /// ### Parameters /// - **current_thread** the current thread /// - **machine** the machine where the threads are executed - pub fn acquire(&mut self, current_thread: Rc>, machine: &mut Machine) { + pub fn acquire(&mut self, current_thread: Option>>, machine: &mut Machine) { let old_status = machine.interrupt.set_status(InterruptOff); if self.free { self.free = false; self.owner = current_thread; } else { - self.waiting_queue.push(Rc::clone(¤t_thread)); - self.thread_manager.borrow_mut().thread_sleep(current_thread); + match current_thread { + Some(x) => { + self.waiting_queue.push(Rc::clone(&x)); + self.thread_manager.borrow_mut().thread_sleep(x) + }, + None => () + } } machine.interrupt.set_status(old_status); @@ -120,8 +139,11 @@ impl Lock { if self.held_by_current_thread(current_thread) { if self.waiting_queue.peek() != None { - self.owner = self.waiting_queue.pop().unwrap(); - scheduler.ready_to_run(Rc::clone(&self.owner)); + self.owner = Some(self.waiting_queue.pop().unwrap()); + match &self.owner { + Some(x) => scheduler.ready_to_run(Rc::clone(&x)), + None => () + } } else { self.free = true; } @@ -147,6 +169,14 @@ pub struct Condition{ impl Condition { + /// Initializes a Condition, so that it can be used for synchronization. + /// + /// ### Parameters + /// - *thread_manager* Thread manager which managing threads + pub fn new(thread_manager: Rc>) -> Condition { + Condition{ waiting_queue: List::new(), thread_manager } + } + /// Block the calling thread (put it in the wait queue). /// This operation must be atomic, so we need to disable interrupts. ///