Test interaction between priority donation and thread_set_priority().
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 18 May 2006 19:37:03 +0000 (19:37 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Thu, 18 May 2006 19:37:03 +0000 (19:37 +0000)
Suggestion from Godmar Back.

TODO
doc/threads.texi
src/tests/threads/Make.tests
src/tests/threads/priority-donate-lower.c [new file with mode: 0644]
src/tests/threads/priority-donate-lower.ck [new file with mode: 0644]
src/tests/threads/tests.c
src/tests/threads/tests.h

diff --git a/TODO b/TODO
index ccc9362c30a0e747500869ce7d96a05ef910ad53..080eb600050edc583cfb30d16e2daf3638a8bae0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -21,22 +21,6 @@ Add a system call "get_kernel_memory_information".  User programs
 could engage in a variety of activities and notice leaks by checking
 the kernel memory statistics.
 
-From: "Godmar Back" <godmar@gmail.com>
-Subject: set_priority & donation - a TODO item
-To: "Ben Pfaff" <blp@cs.stanford.edu>
-Date: Mon, 20 Feb 2006 22:20:26 -0500
-
-Ben,
-
-it seems that there are currently no tests that check the proper
-behavior of thread_set_priority() when called by a thread that is
-running under priority donation.  The proper behavior, I assume, is to
-temporarily drop the donation if the set priority is higher, and to
-reassume the donation should the thread subsequently set its own
-priority again to a level that's lower than a still active donation.
-
- - Godmar
-
 From: Godmar Back <godmar@gmail.com>
 Subject: on caching in project 4
 To: Ben Pfaff <blp@cs.stanford.edu>
@@ -111,8 +95,6 @@ via Godmar Back:
 
   - Add extra credit:
 
-    . Low-level x86 stuff, like paged page tables.
-
     . Specifics on how to implement sbrk, malloc.
 
     . Other good ideas.
index f5e60585f685a9b0e8f0779192bb6bff108abc57..eeb17eeac26298c6728c1349abbb5bc3a12f1222 100644 (file)
@@ -714,9 +714,11 @@ preempting whatever thread is currently running.
 
 @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!
 
index 3b6bfd7cf9db0b49bd28ebf11244f2094e006a6f..f1e239eeb9dc6ff614bf21ffe9e9b55c2f5ae1df 100644 (file)
@@ -5,10 +5,10 @@ tests/threads_TESTS = $(addprefix tests/threads/,alarm-single         \
 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
@@ -23,6 +23,7 @@ tests/threads_SRC += tests/threads/priority-donate-multiple.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
diff --git a/src/tests/threads/priority-donate-lower.c b/src/tests/threads/priority-donate-lower.c
new file mode 100644 (file)
index 0000000..3f63db8
--- /dev/null
@@ -0,0 +1,51 @@
+/* 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");
+}
diff --git a/src/tests/threads/priority-donate-lower.ck b/src/tests/threads/priority-donate-lower.ck
new file mode 100644 (file)
index 0000000..b009fd8
--- /dev/null
@@ -0,0 +1,15 @@
+# -*- 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
index b5153728cc195b426699c237aedf9fccaf79abab..3f0327f9f277c588db820f736e7eb5b6d7192edd 100644 (file)
@@ -23,6 +23,7 @@ static const struct test tests[] =
     {"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},
index 1fe839ea847ad16a69b5d01a51f7a7127b6a558b..81e966315553126616f9a71a22d73a59a756bd81 100644 (file)
@@ -17,6 +17,7 @@ extern test_func test_priority_donate_multiple;
 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;