/* A low priority thread 'a' acquires a lock, then waits on a semaphore. Next, a medium priority thread 'b' waits on the same semaphore. Next, a high priority thread 'c' attempts to acquire the lock, donating its priority to the low priority thread 'a'. Next, the main thread signals the semaphore, waking up the low priority thread 'a'. This thread releases the lock, which wakes up the high priority thread 'c'. The high priority thread 'c' signals the semaphore, waking up the medium priority thread 'b'. The high priority thread finishes, then the medium priority thread, then the low priority, and finally the main thread. Written by Godmar Back . */ #include #include "tests/threads/tests.h" #include "threads/init.h" #include "threads/synch.h" #include "threads/thread.h" struct lock_and_sema { struct lock lock; struct semaphore sema; }; static thread_func a_thread_func; static thread_func b_thread_func; static thread_func c_thread_func; void test_priority_donate_sema (void) { struct lock_and_sema ls; /* This test does not work with the MLFQS. */ ASSERT (!enable_mlfqs); /* Make sure our priority is the default. */ ASSERT (thread_get_priority () == PRI_DEFAULT); lock_init (&ls.lock); sema_init (&ls.sema, 0); thread_create ("low", PRI_DEFAULT - 1, a_thread_func, &ls); thread_create ("med", PRI_DEFAULT - 3, b_thread_func, &ls); thread_create ("high", PRI_DEFAULT - 5, c_thread_func, &ls); sema_up (&ls.sema); msg ("Threads c, b, a should have just finished, in that order."); } static void a_thread_func (void *ls_) { struct lock_and_sema *ls = ls_; lock_acquire (&ls->lock); msg ("Thread a acquired lock."); sema_down (&ls->sema); msg ("Thread a downed semaphore."); lock_release (&ls->lock); msg ("Thread a finished."); } static void b_thread_func (void *ls_) { struct lock_and_sema *ls = ls_; sema_down (&ls->sema); msg ("Thread b finished."); } static void c_thread_func (void *ls_) { struct lock_and_sema *ls = ls_; lock_acquire (&ls->lock); msg ("Thread c acquired lock."); sema_up (&ls->sema); lock_release (&ls->lock); msg ("Thread c finished."); }