From ac1525683728d7b3ab644e729e6658d435914d85 Mon Sep 17 00:00:00 2001 From: manuel Date: Fri, 11 May 2012 15:10:44 +0200 Subject: add new test for priority donation with conditions --- tests/threads/Make.tests | 3 +- tests/threads/priority-donate-condvar.c | 97 ++++++++++++++++++++++++++++++++ tests/threads/priority-donate-condvar.ck | 18 ++++++ tests/threads/tests.c | 1 + tests/threads/tests.h | 1 + 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 tests/threads/priority-donate-condvar.c create mode 100644 tests/threads/priority-donate-condvar.ck diff --git a/tests/threads/Make.tests b/tests/threads/Make.tests index dbdfd0c..a72659b 100644 --- a/tests/threads/Make.tests +++ b/tests/threads/Make.tests @@ -7,7 +7,7 @@ alarm-negative priority-change priority-donate-one \ priority-donate-multiple priority-donate-multiple2 \ priority-donate-nest priority-donate-sema priority-donate-lower \ priority-fifo priority-preempt priority-sema priority-condvar \ -priority-donate-chain) +priority-donate-chain priority-donate-condvar) # Sources for tests. @@ -29,6 +29,7 @@ tests/threads_SRC += tests/threads/priority-preempt.c tests/threads_SRC += tests/threads/priority-sema.c tests/threads_SRC += tests/threads/priority-condvar.c tests/threads_SRC += tests/threads/priority-donate-chain.c +tests/threads_SRC += tests/threads/priority-donate-condvar.c # Not used in SS 2012 MLFQS_TESTS = mlfqs-load-1 mlfqs-load-60 mlfqs-load-avg mlfqs-recent-1 \ diff --git a/tests/threads/priority-donate-condvar.c b/tests/threads/priority-donate-condvar.c new file mode 100644 index 0000000..321a58a --- /dev/null +++ b/tests/threads/priority-donate-condvar.c @@ -0,0 +1,97 @@ +/* Basically that's the same test as priority-donate-sema but using + conditions instead of semaphores. + + Low priority thread L acquires a lock, then blocks waiting for + the condition. Medium priority thread M then blocks waiting for + the same condition. Next, high priority thread H attempts to + acquire the lock, donating its priority to L. + + Next, the main thread signals the condition, waking up L. L + releases the lock, which wakes up H. H signals the condition, + waking up M. H terminates, then M, then L, and finally the + main thread. + + Written by Manuel Mausz . */ + +#include +#include "tests/threads/tests.h" +#include "threads/init.h" +#include "threads/synch.h" +#include "threads/thread.h" + +struct lock_and_cond + { + struct lock lock; + struct lock lockc; + struct condition cond; + }; + +static thread_func l_thread_func; +static thread_func m_thread_func; +static thread_func h_thread_func; + +void +test_priority_donate_condvar (void) +{ + struct lock_and_cond ls; + + /* 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 (&ls.lock); + lock_init (&ls.lockc); + cond_init (&ls.cond); + thread_create ("low", PRI_DEFAULT + 1, l_thread_func, &ls); + thread_create ("med", PRI_DEFAULT + 3, m_thread_func, &ls); + thread_create ("high", PRI_DEFAULT + 5, h_thread_func, &ls); + lock_acquire (&ls.lockc); + msg ("Signaling..."); + cond_signal (&ls.cond, &ls.lockc); + lock_release (&ls.lockc); + msg ("Main thread finished."); +} + +static void +l_thread_func (void *ls_) +{ + struct lock_and_cond *ls = ls_; + + lock_acquire (&ls->lock); + msg ("Thread L acquired lock."); + lock_acquire (&ls->lockc); + cond_wait (&ls->cond, &ls->lockc); + lock_release (&ls->lockc); + msg ("Thread L woke up."); + lock_release (&ls->lock); + msg ("Thread L finished."); +} + +static void +m_thread_func (void *ls_) +{ + struct lock_and_cond *ls = ls_; + + lock_acquire (&ls->lockc); + cond_wait (&ls->cond, &ls->lockc); + lock_release (&ls->lockc); + msg ("Thread M finished."); +} + +static void +h_thread_func (void *ls_) +{ + struct lock_and_cond *ls = ls_; + + lock_acquire (&ls->lock); + msg ("Thread H acquired lock."); + + lock_acquire (&ls->lockc); + msg ("Signaling..."); + cond_signal (&ls->cond, &ls->lockc); + lock_release (&ls->lockc); + lock_release (&ls->lock); + msg ("Thread H finished."); +} diff --git a/tests/threads/priority-donate-condvar.ck b/tests/threads/priority-donate-condvar.ck new file mode 100644 index 0000000..3ffe51c --- /dev/null +++ b/tests/threads/priority-donate-condvar.ck @@ -0,0 +1,18 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(priority-donate-condvar) begin +(priority-donate-condvar) Thread L acquired lock. +(priority-donate-condvar) Signaling... +(priority-donate-condvar) Thread L woke up. +(priority-donate-condvar) Thread H acquired lock. +(priority-donate-condvar) Signaling... +(priority-donate-condvar) Thread H finished. +(priority-donate-condvar) Thread M finished. +(priority-donate-condvar) Thread L finished. +(priority-donate-condvar) Main thread finished. +(priority-donate-condvar) end +EOF +pass; diff --git a/tests/threads/tests.c b/tests/threads/tests.c index af15aee..d19ab24 100644 --- a/tests/threads/tests.c +++ b/tests/threads/tests.c @@ -25,6 +25,7 @@ static const struct test tests[] = {"priority-donate-sema", test_priority_donate_sema}, {"priority-donate-lower", test_priority_donate_lower}, {"priority-donate-chain", test_priority_donate_chain}, + {"priority-donate-condvar", test_priority_donate_condvar}, {"priority-fifo", test_priority_fifo}, {"priority-preempt", test_priority_preempt}, {"priority-sema", test_priority_sema}, diff --git a/tests/threads/tests.h b/tests/threads/tests.h index cd9d489..cc51fc9 100644 --- a/tests/threads/tests.h +++ b/tests/threads/tests.h @@ -19,6 +19,7 @@ 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_donate_chain; +extern test_func test_priority_donate_condvar; extern test_func test_priority_fifo; extern test_func test_priority_preempt; extern test_func test_priority_sema; -- cgit v1.2.3