Fix two bugs in the base Pintos code:
[pintos-anon] / src / tests / threads / priority-donate-nest.c
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
18 struct locks 
19   {
20     struct lock *a;
21     struct lock *b;
22   };
23
24 static thread_func medium_thread_func;
25 static thread_func high_thread_func;
26
27 void
28 test_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
63 static void
64 medium_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
85 static void
86 high_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 }