00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include "tests/threads/tests.h"
00029 #include "threads/init.h"
00030 #include "threads/synch.h"
00031 #include "threads/thread.h"
00032
00033 #define NESTING_DEPTH 8
00034
00035 struct lock_pair
00036 {
00037 struct lock *second;
00038 struct lock *first;
00039 };
00040
00041 static thread_func donor_thread_func;
00042 static thread_func interloper_thread_func;
00043
00044 void
00045 test_priority_donate_chain (void)
00046 {
00047 int i;
00048 struct lock locks[NESTING_DEPTH - 1];
00049 struct lock_pair lock_pairs[NESTING_DEPTH];
00050
00051
00052 ASSERT (!thread_mlfqs);
00053
00054 thread_set_priority (PRI_MIN);
00055
00056 for (i = 0; i < NESTING_DEPTH - 1; i++)
00057 lock_init (&locks[i]);
00058
00059 lock_acquire (&locks[0]);
00060 msg ("%s got lock.", thread_name ());
00061
00062 for (i = 1; i < NESTING_DEPTH; i++)
00063 {
00064 char name[16];
00065 int thread_priority;
00066
00067 snprintf (name, sizeof name, "thread %d", i);
00068 thread_priority = PRI_MIN + i * 3;
00069 lock_pairs[i].first = i < NESTING_DEPTH - 1 ? locks + i: NULL;
00070 lock_pairs[i].second = locks + i - 1;
00071
00072 thread_create (name, thread_priority, donor_thread_func, lock_pairs + i);
00073 msg ("%s should have priority %d. Actual priority: %d.",
00074 thread_name (), thread_priority, thread_get_priority ());
00075
00076 snprintf (name, sizeof name, "interloper %d", i);
00077 thread_create (name, thread_priority - 1, interloper_thread_func, NULL);
00078 }
00079
00080 lock_release (&locks[0]);
00081 msg ("%s finishing with priority %d.", thread_name (),
00082 thread_get_priority ());
00083 }
00084
00085 static void
00086 donor_thread_func (void *locks_)
00087 {
00088 struct lock_pair *locks = locks_;
00089
00090 if (locks->first)
00091 lock_acquire (locks->first);
00092
00093 lock_acquire (locks->second);
00094 msg ("%s got lock", thread_name ());
00095
00096 lock_release (locks->second);
00097 msg ("%s should have priority %d. Actual priority: %d",
00098 thread_name (), (NESTING_DEPTH - 1) * 3,
00099 thread_get_priority ());
00100
00101 if (locks->first)
00102 lock_release (locks->first);
00103
00104 msg ("%s finishing with priority %d.", thread_name (),
00105 thread_get_priority ());
00106 }
00107
00108 static void
00109 interloper_thread_func (void *arg_ UNUSED)
00110 {
00111 msg ("%s finished.", thread_name ());
00112 }
00113
00114