summaryrefslogtreecommitdiffstats
path: root/tests/threads/priority-donate-nest.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/threads/priority-donate-nest.c')
-rw-r--r--tests/threads/priority-donate-nest.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/tests/threads/priority-donate-nest.c b/tests/threads/priority-donate-nest.c
new file mode 100644
index 0000000..3a3a9a5
--- /dev/null
+++ b/tests/threads/priority-donate-nest.c
@@ -0,0 +1,94 @@
1/* Low-priority main thread L acquires lock A. Medium-priority
2 thread M then acquires lock B then blocks on acquiring lock A.
3 High-priority thread H then blocks on acquiring lock B. Thus,
4 thread H donates its priority to M, which in turn donates it
5 to thread L.
6
7 Based on a test originally submitted for Stanford's CS 140 in
8 winter 1999 by Matt Franklin <startled@leland.stanford.edu>,
9 Greg Hutchins <gmh@leland.stanford.edu>, Yu Ping Hu
10 <yph@cs.stanford.edu>. Modified by arens. */
11
12#include <stdio.h>
13#include "tests/threads/tests.h"
14#include "threads/init.h"
15#include "threads/synch.h"
16#include "threads/thread.h"
17
18struct locks
19 {
20 struct lock *a;
21 struct lock *b;
22 };
23
24static thread_func medium_thread_func;
25static thread_func high_thread_func;
26
27void
28test_priority_donate_nest (void)
29{
30 struct lock a, b;
31 struct locks locks;
32
33 /* This test does not work with the MLFQS. */
34 ASSERT (!thread_mlfqs);
35
36 /* Make sure our priority is the default. */
37 ASSERT (thread_get_priority () == PRI_DEFAULT);
38
39 lock_init (&a);
40 lock_init (&b);
41
42 lock_acquire (&a);
43
44 locks.a = &a;
45 locks.b = &b;
46 thread_create ("medium", PRI_DEFAULT + 1, medium_thread_func, &locks);
47 thread_yield ();
48 msg ("Low thread should have priority %d. Actual priority: %d.",
49 PRI_DEFAULT + 1, thread_get_priority ());
50
51 thread_create ("high", PRI_DEFAULT + 2, high_thread_func, &b);
52 thread_yield ();
53 msg ("Low thread should have priority %d. Actual priority: %d.",
54 PRI_DEFAULT + 2, thread_get_priority ());
55
56 lock_release (&a);
57 thread_yield ();
58 msg ("Medium thread should just have finished.");
59 msg ("Low thread should have priority %d. Actual priority: %d.",
60 PRI_DEFAULT, thread_get_priority ());
61}
62
63static void
64medium_thread_func (void *locks_)
65{
66 struct locks *locks = locks_;
67
68 lock_acquire (locks->b);
69 lock_acquire (locks->a);
70
71 msg ("Medium thread should have priority %d. Actual priority: %d.",
72 PRI_DEFAULT + 2, thread_get_priority ());
73 msg ("Medium thread got the lock.");
74
75 lock_release (locks->a);
76 thread_yield ();
77
78 lock_release (locks->b);
79 thread_yield ();
80
81 msg ("High thread should have just finished.");
82 msg ("Middle thread finished.");
83}
84
85static void
86high_thread_func (void *lock_)
87{
88 struct lock *lock = lock_;
89
90 lock_acquire (lock);
91 msg ("High thread got the lock.");
92 lock_release (lock);
93 msg ("High thread finished.");
94}