diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 5d56023..c94426c 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -64,7 +64,7 @@ impl Semaphore { /// - **scheduler** the scheduler which determine which thread to execute pub fn v(&mut self, machine: &mut Machine, scheduler: &mut Scheduler){ let old_status = machine.interrupt.set_status(InterruptOff); - self.counter -= 1; + self.counter += 1; if self.waiting_queue.peek() != None { scheduler.ready_to_run(self.waiting_queue.pop().unwrap()); } @@ -150,6 +150,7 @@ impl Lock { } } else { self.free = true; + self.owner = None; } } @@ -232,4 +233,122 @@ impl Condition { } +} + +#[test] +fn test_semaphore_single() { + // Init + let thread_manager = Rc::new(RefCell::new(ThreadManager::new())); + let mut semaphore = Semaphore::new(1, thread_manager); + let mut machine = Machine::init_machine(); + let mut scheduler = Scheduler::new(); + let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); + // P + semaphore.p(thread, &mut machine); + assert_eq!(semaphore.counter, 0); + assert!(semaphore.waiting_queue.is_empty()); + // V + semaphore.v(&mut machine, &mut scheduler); + assert_eq!(semaphore.counter, 1); + assert!(semaphore.waiting_queue.is_empty()); +} + +#[test] +fn test_semaphore_multiple() { + // Init + let thread_manager = Rc::new(RefCell::new(ThreadManager::new())); + let mut semaphore = Semaphore::new(2, Rc::clone(&thread_manager)); + let mut machine = Machine::init_machine(); + let mut scheduler = Scheduler::new(); + 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"))); + // P + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); + semaphore.p(thread1, &mut machine); + assert_eq!(semaphore.counter, 1); + assert!(semaphore.waiting_queue.is_empty()); + + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); + semaphore.p(thread2, &mut machine); + assert_eq!(semaphore.counter, 0); + assert!(semaphore.waiting_queue.is_empty()); + + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread3))); + semaphore.p(thread3, &mut machine); + assert_eq!(semaphore.counter, -1); + assert!(semaphore.waiting_queue.iter().count() == 1); + + // V + semaphore.v(&mut machine, &mut scheduler); + assert_eq!(semaphore.counter, 0); + assert!(semaphore.waiting_queue.is_empty()); + + semaphore.v(&mut machine, &mut scheduler); + assert_eq!(semaphore.counter, 1); + assert!(semaphore.waiting_queue.is_empty()); + + semaphore.v(&mut machine, &mut scheduler); + assert_eq!(semaphore.counter, 2); + assert!(semaphore.waiting_queue.is_empty()); +} + + + +#[test] +fn test_lock_simple() { + let thread_manager = Rc::new(RefCell::new(ThreadManager::new())); + let mut machine = Machine::init_machine(); + let mut scheduler = Scheduler::new(); + let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread))); + let mut lock = Lock::new(Rc::clone(&thread_manager)); + + assert!(lock.free); + lock.acquire(Some(Rc::clone(&thread)), &mut machine); + assert!(lock.held_by_current_thread(Rc::clone(&thread))); + + assert!(!lock.free); + lock.release(&mut machine, &mut scheduler, Rc::clone(&thread)); + assert!(!lock.held_by_current_thread(thread)); + assert!(lock.free); +} + +#[test] +fn test_lock_multiple() { + let thread_manager = Rc::new(RefCell::new(ThreadManager::new())); + let mut machine = Machine::init_machine(); + let mut scheduler = Scheduler::new(); + 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"))); + + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread1))); + let mut lock = Lock::new(Rc::clone(&thread_manager)); + + assert!(lock.free); + lock.acquire(Some(Rc::clone(&thread1)), &mut machine); + assert!(lock.held_by_current_thread(Rc::clone(&thread1))); + assert!(!lock.free); + + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); + lock.acquire(Some(Rc::clone(&thread2)), &mut machine); + thread_manager.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); + + lock.release(&mut machine, &mut scheduler, Rc::clone(&thread1)); + assert!(!lock.held_by_current_thread(thread1)); + assert!(lock.held_by_current_thread(Rc::clone(&thread2))); + assert!(!lock.free); + + thread_manager.borrow_mut().set_g_current_thread(Some(Rc::clone(&thread2))); + + + lock.release(&mut machine, &mut scheduler, Rc::clone(&thread2)); + assert!(!lock.held_by_current_thread(thread2)); + assert!(lock.free); } \ No newline at end of file