Suggestion from Godmar Back.
@item How does @func{thread_set_priority} affect a thread receiving donations?
-It should do something sensible, but no particular behavior is
-required. None of the test cases call @func{thread_set_priority} from a
-thread while it is receiving a priority donation.
+It sets the thread's base priority. The thread's effective priority
+becomes the higher of the newly set priority or the highest donated
+priority. When the donations are released, the thread's priority
+becomes the one set through the function call. This behavior is checked
+by the @code{priority-donate-lower} test.
@item Calling @func{printf} in @func{sema_up} or @func{sema_down} reboots!
alarm-multiple alarm-simultaneous alarm-priority alarm-zero \
alarm-negative priority-change priority-donate-one \
priority-donate-multiple priority-donate-multiple2 \
-priority-donate-nest priority-donate-sema priority-fifo \
-priority-preempt priority-sema priority-condvar mlfqs-load-1 \
-mlfqs-load-60 mlfqs-load-avg mlfqs-recent-1 mlfqs-fair-2 mlfqs-fair-20 \
-mlfqs-nice-2 mlfqs-nice-10 mlfqs-block)
+priority-donate-nest priority-donate-sema priority-donate-lower \
+priority-fifo priority-preempt priority-sema priority-condvar \
+mlfqs-load-1 mlfqs-load-60 mlfqs-load-avg mlfqs-recent-1 mlfqs-fair-2 \
+mlfqs-fair-20 mlfqs-nice-2 mlfqs-nice-10 mlfqs-block)
# Sources for tests.
tests/threads_SRC = tests/threads/tests.c
tests/threads_SRC += tests/threads/priority-donate-multiple2.c
tests/threads_SRC += tests/threads/priority-donate-nest.c
tests/threads_SRC += tests/threads/priority-donate-sema.c
+tests/threads_SRC += tests/threads/priority-donate-lower.c
tests/threads_SRC += tests/threads/priority-fifo.c
tests/threads_SRC += tests/threads/priority-preempt.c
tests/threads_SRC += tests/threads/priority-sema.c
--- /dev/null
+/* The main thread acquires a lock. Then it creates a
+ higher-priority thread that blocks acquiring the lock, causing
+ it to donate their priorities to the main thread. The main
+ thread attempts to lower its priority, which should not take
+ effect until the donation is released. */
+
+#include <stdio.h>
+#include "tests/threads/tests.h"
+#include "threads/init.h"
+#include "threads/synch.h"
+#include "threads/thread.h"
+
+static thread_func acquire_thread_func;
+
+void
+test_priority_donate_lower (void)
+{
+ struct lock lock;
+
+ /* This test does not work with the MLFQS. */
+ ASSERT (!enable_mlfqs);
+
+ /* Make sure our priority is the default. */
+ ASSERT (thread_get_priority () == PRI_DEFAULT);
+
+ lock_init (&lock);
+ lock_acquire (&lock);
+ thread_create ("acquire", PRI_DEFAULT + 10, acquire_thread_func, &lock);
+ msg ("Main thread should have priority %d. Actual priority: %d.",
+ PRI_DEFAULT + 10, thread_get_priority ());
+
+ msg ("Lowering base priority...");
+ thread_set_priority (PRI_DEFAULT - 10);
+ msg ("Main thread should have priority %d. Actual priority: %d.",
+ PRI_DEFAULT + 10, thread_get_priority ());
+ lock_release (&lock);
+ msg ("acquire must already have finished.");
+ msg ("Main thread should have priority %d. Actual priority: %d.",
+ PRI_DEFAULT - 10, thread_get_priority ());
+}
+
+static void
+acquire_thread_func (void *lock_)
+{
+ struct lock *lock = lock_;
+
+ lock_acquire (lock);
+ msg ("acquire: got the lock");
+ lock_release (lock);
+ msg ("acquire: done");
+}
--- /dev/null
+# -*- perl -*-
+use strict;
+use warnings;
+use tests::tests;
+check_expected ([<<'EOF']);
+(priority-donate-lower) begin
+(priority-donate-lower) Main thread should have priority 41. Actual priority: 41.
+(priority-donate-lower) Lowering base priority...
+(priority-donate-lower) Main thread should have priority 41. Actual priority: 41.
+(priority-donate-lower) acquire: got the lock
+(priority-donate-lower) acquire: done
+(priority-donate-lower) acquire must already have finished.
+(priority-donate-lower) Main thread should have priority 21. Actual priority: 21.
+(priority-donate-lower) end
+EOF
{"priority-donate-multiple2", test_priority_donate_multiple2},
{"priority-donate-nest", test_priority_donate_nest},
{"priority-donate-sema", test_priority_donate_sema},
+ {"priority-donate-lower", test_priority_donate_lower},
{"priority-fifo", test_priority_fifo},
{"priority-preempt", test_priority_preempt},
{"priority-sema", test_priority_sema},
extern test_func test_priority_donate_multiple2;
extern test_func test_priority_donate_sema;
extern test_func test_priority_donate_nest;
+extern test_func test_priority_donate_lower;
extern test_func test_priority_fifo;
extern test_func test_priority_preempt;
extern test_func test_priority_sema;