diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index a2038e6..98a1f76 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -1,8 +1,11 @@ use crate::utility::list::List; use crate::kernel::thread::Thread; -use std::rc::Rc; use crate::simulator::interrupt::InterruptStatus::InterruptOff; use crate::simulator::machine::Machine; +use std::rc::Rc; + + +use super::scheduler::Scheduler; pub struct Semaphore{ @@ -13,9 +16,9 @@ pub struct Semaphore{ impl Semaphore{ - pub fn p(&mut self, current_thread:Rc, machine: &mut Machine){ + pub fn p(&mut self, current_thread: Rc, machine: &mut Machine){ let old_status = machine.interrupt.set_status(InterruptOff); - self.counter-=1; + self.counter -= 1; if self.counter < 0 { self.waiting_queue.push(Rc::clone(¤t_thread)); current_thread.sleep(); @@ -23,12 +26,11 @@ impl Semaphore{ machine.interrupt.set_status(old_status); } - pub fn v(&mut self, current_thread:Rc, machine: &mut Machine){ + pub fn v(&mut self, machine: &mut Machine, scheduler: &mut Scheduler){ let old_status = machine.interrupt.set_status(InterruptOff); - self.counter-=1; - if self.waiting_queue.peek() == None { - self.waiting_queue.push(Rc::clone(¤t_thread)); - current_thread.sleep(); + self.counter -= 1; + if self.waiting_queue.peek() != None { + scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); } machine.interrupt.set_status(old_status); } @@ -36,8 +38,83 @@ impl Semaphore{ pub struct Lock{ + owner: Rc, + waiting_queue:List>, + free: bool + +} + +impl Lock { + pub fn acquire(&mut self, machine: &mut Machine, current_thread: Rc) { + 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)); + current_thread.sleep(); + } + + machine.interrupt.set_status(old_status); + } + + pub fn release(&mut self, machine: &mut Machine, scheduler: &mut Scheduler, current_thread: Rc) { + let old_status = machine.interrupt.set_status(InterruptOff); + + if self.is_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)); + } else { + self.free = true; + } + } + + machine.interrupt.set_status(old_status); + } + + pub fn is_held_by_current_thread(&mut self, current_thread: Rc) -> bool { + Rc::ptr_eq(&self.owner, ¤t_thread) + } } pub struct Condition{ + waiting_queue:List> + +} + +impl Condition { + + pub fn wait(&mut self, machine: &mut Machine, current_thread: Rc) { + let old_status = machine.interrupt.set_status(InterruptOff); + + self.waiting_queue.push(Rc::clone(¤t_thread)); + current_thread.sleep(); + + machine.interrupt.set_status(old_status); + } + + pub fn signal(&mut self, machine: &mut Machine, scheduler: &mut Scheduler) { + let old_status = machine.interrupt.set_status(InterruptOff); + + if self.waiting_queue.peek() != None { + scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + } + + machine.interrupt.set_status(old_status); + + } + + pub fn broadcast(&mut self, machine: &mut Machine, scheduler: &mut Scheduler) { + let old_status = machine.interrupt.set_status(InterruptOff); + + while self.waiting_queue.peek() != None { + scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); + } + machine.interrupt.set_status(old_status); + + } + } \ No newline at end of file