1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
/* 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 <startled@leland.stanford.edu>,
Greg Hutchins <gmh@leland.stanford.edu>, Yu Ping Hu
<yph@cs.stanford.edu>. Modified by arens. */
#include <stdio.h>
#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.");
}
|