summaryrefslogtreecommitdiffstats
path: root/pintos-progos/tests/threads/priority-donate-chain.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-03-26 12:54:45 +0200
committermanuel <manuel@mausz.at>2012-03-26 12:54:45 +0200
commitb5f0874cd96ee2a62aabc645b9626c2749cb6a01 (patch)
tree1262e4bbe0634de6650be130c36e0538240f4cbf /pintos-progos/tests/threads/priority-donate-chain.c
downloadprogos-b5f0874cd96ee2a62aabc645b9626c2749cb6a01.tar.gz
progos-b5f0874cd96ee2a62aabc645b9626c2749cb6a01.tar.bz2
progos-b5f0874cd96ee2a62aabc645b9626c2749cb6a01.zip
initial pintos checkin
Diffstat (limited to 'pintos-progos/tests/threads/priority-donate-chain.c')
-rw-r--r--pintos-progos/tests/threads/priority-donate-chain.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/pintos-progos/tests/threads/priority-donate-chain.c b/pintos-progos/tests/threads/priority-donate-chain.c
new file mode 100644
index 0000000..3ffabca
--- /dev/null
+++ b/pintos-progos/tests/threads/priority-donate-chain.c
@@ -0,0 +1,114 @@
1/* The main thread set its priority to PRI_MIN and creates 7 threads
2 (thread 1..7) with priorities PRI_MIN + 3, 6, 9, 12, ...
3 The main thread initializes 8 locks: lock 0..7 and acquires lock 0.
4
5 When thread[i] starts, it first acquires lock[i] (unless i == 7.)
6 Subsequently, thread[i] attempts to acquire lock[i-1], which is held by
7 thread[i-1], except for lock[0], which is held by the main thread.
8 Because the lock is held, thread[i] donates its priority to thread[i-1],
9 which donates to thread[i-2], and so on until the main thread
10 receives the donation.
11
12 After threads[1..7] have been created and are blocked on locks[0..7],
13 the main thread releases lock[0], unblocking thread[1], and being
14 preempted by it.
15 Thread[1] then completes acquiring lock[0], then releases lock[0],
16 then releases lock[1], unblocking thread[2], etc.
17 Thread[7] finally acquires & releases lock[7] and exits, allowing
18 thread[6], then thread[5] etc. to run and exit until finally the
19 main thread exits.
20
21 In addition, interloper threads are created at priority levels
22 p = PRI_MIN + 2, 5, 8, 11, ... which should not be run until the
23 corresponding thread with priority p + 1 has finished.
24
25 Written by Godmar Back <gback@cs.vt.edu> */
26
27#include <stdio.h>
28#include "tests/threads/tests.h"
29#include "threads/init.h"
30#include "threads/synch.h"
31#include "threads/thread.h"
32
33#define NESTING_DEPTH 8
34
35struct lock_pair
36 {
37 struct lock *second;
38 struct lock *first;
39 };
40
41static thread_func donor_thread_func;
42static thread_func interloper_thread_func;
43
44void
45test_priority_donate_chain (void)
46{
47 int i;
48 struct lock locks[NESTING_DEPTH - 1];
49 struct lock_pair lock_pairs[NESTING_DEPTH];
50
51 /* This test does not work with the MLFQS. */
52 ASSERT (!thread_mlfqs);
53
54 thread_set_priority (PRI_MIN);
55
56 for (i = 0; i < NESTING_DEPTH - 1; i++)
57 lock_init (&locks[i]);
58
59 lock_acquire (&locks[0]);
60 msg ("%s got lock.", thread_name ());
61
62 for (i = 1; i < NESTING_DEPTH; i++)
63 {
64 char name[16];
65 int thread_priority;
66
67 snprintf (name, sizeof name, "thread %d", i);
68 thread_priority = PRI_MIN + i * 3;
69 lock_pairs[i].first = i < NESTING_DEPTH - 1 ? locks + i: NULL;
70 lock_pairs[i].second = locks + i - 1;
71
72 thread_create (name, thread_priority, donor_thread_func, lock_pairs + i);
73 msg ("%s should have priority %d. Actual priority: %d.",
74 thread_name (), thread_priority, thread_get_priority ());
75
76 snprintf (name, sizeof name, "interloper %d", i);
77 thread_create (name, thread_priority - 1, interloper_thread_func, NULL);
78 }
79
80 lock_release (&locks[0]);
81 msg ("%s finishing with priority %d.", thread_name (),
82 thread_get_priority ());
83}
84
85static void
86donor_thread_func (void *locks_)
87{
88 struct lock_pair *locks = locks_;
89
90 if (locks->first)
91 lock_acquire (locks->first);
92
93 lock_acquire (locks->second);
94 msg ("%s got lock", thread_name ());
95
96 lock_release (locks->second);
97 msg ("%s should have priority %d. Actual priority: %d",
98 thread_name (), (NESTING_DEPTH - 1) * 3,
99 thread_get_priority ());
100
101 if (locks->first)
102 lock_release (locks->first);
103
104 msg ("%s finishing with priority %d.", thread_name (),
105 thread_get_priority ());
106}
107
108static void
109interloper_thread_func (void *arg_ UNUSED)
110{
111 msg ("%s finished.", thread_name ());
112}
113
114// vim: sw=2