/* Low-priority main thread L acquires lock A. Medium-priority thread M then acquires lock B then blocks on acquiring lock A. High-priority thread H then blocks on acquiring lock B. Thus, thread H donates its priority to M, which in turn donates it to thread L. Based on a test originally submitted for Stanford's CS 140 in winter 1999 by Matt Franklin , Greg Hutchins , Yu Ping Hu . Modified by arens. */ #include #include "tests/threads/tests.h" #include "threads/init.h" #include "threads/synch.h" #include "threads/thread.h" struct locks { struct lock *a; struct lock *b; }; static thread_func medium_thread_func; static thread_func high_thread_func; void test_priority_donate_nest (void) { struct lock a, b; struct locks locks; /* This test does not work with the MLFQS. */ ASSERT (!thread_mlfqs); /* Make sure our priority is the default. */ ASSERT (thread_get_priority () == PRI_DEFAULT); lock_init (&a); lock_init (&b); lock_acquire (&a); locks.a = &a; locks.b = &b; thread_create ("medium", PRI_DEFAULT + 1, medium_thread_func, &locks); thread_yield (); msg ("Low thread should have priority %d. Actual priority: %d.", PRI_DEFAULT + 1, thread_get_priority ()); thread_create ("high", PRI_DEFAULT + 2, high_thread_func, &b); thread_yield (); msg ("Low thread should have priority %d. Actual priority: %d.", PRI_DEFAULT + 2, thread_get_priority ()); lock_release (&a); thread_yield (); msg ("Medium thread should just have finished."); msg ("Low thread should have priority %d. Actual priority: %d.", PRI_DEFAULT, thread_get_priority ()); } static void medium_thread_func (void *locks_) { struct locks *locks = locks_; lock_acquire (locks->b); lock_acquire (locks->a); msg ("Medium thread should have priority %d. Actual priority: %d.", PRI_DEFAULT + 2, thread_get_priority ()); msg ("Medium thread got the lock."); lock_release (locks->a); thread_yield (); lock_release (locks->b); thread_yield (); msg ("High thread should have just finished."); msg ("Middle thread finished."); } static void high_thread_func (void *lock_) { struct lock *lock = lock_; lock_acquire (lock); msg ("High thread got the lock."); lock_release (lock); msg ("High thread finished."); }