threads.
Suggested by Godmar Back.
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-nice-2 mlfqs-nice-10 mlfqs-block)
# Sources for tests.
tests/threads_SRC = tests/threads/tests.c
tests/threads_SRC += tests/threads/mlfqs-load-avg.c
tests/threads_SRC += tests/threads/mlfqs-recent-1.c
tests/threads_SRC += tests/threads/mlfqs-fair.c
+tests/threads_SRC += tests/threads/mlfqs-block.c
MLFQS_OUTPUTS = \
tests/threads/mlfqs-load-1.output \
tests/threads/mlfqs-fair-2.output \
tests/threads/mlfqs-fair-20.output \
tests/threads/mlfqs-nice-2.output \
-tests/threads/mlfqs-nice-10.output
+tests/threads/mlfqs-nice-10.output \
+tests/threads/mlfqs-block.output
$(MLFQS_OUTPUTS): KERNELFLAGS += -mlfqs
$(MLFQS_OUTPUTS): TIMEOUT = 240
4 mlfqs-nice-2
2 mlfqs-nice-10
+
+5 mlfqs-block
--- /dev/null
+/* Checks that recent_cpu and priorities are updated for blocked
+ threads.
+
+ The main thread sleeps for 25 seconds, spins for 5 seconds,
+ then releases a lock. The "block" thread spins for 20 seconds
+ then attempts to acquire the lock, which will block for 10
+ seconds (until the main thread releases it). If recent_cpu
+ decays properly while the "block" thread sleeps, then the
+ block thread should be immediately scheduled when the main
+ thread releases the lock,. */
+
+#include <stdio.h>
+#include "tests/threads/tests.h"
+#include "threads/init.h"
+#include "threads/malloc.h"
+#include "threads/synch.h"
+#include "threads/thread.h"
+#include "devices/timer.h"
+
+static void block_thread (void *lock_);
+
+void
+test_mlfqs_block (void)
+{
+ int64_t start_time;
+ struct lock lock;
+
+ ASSERT (enable_mlfqs);
+
+ msg ("Main thread acquiring lock.");
+ lock_init (&lock);
+ lock_acquire (&lock);
+
+ msg ("Main thread creating block thread, sleeping 25 seconds...");
+ thread_create ("block", PRI_DEFAULT, block_thread, &lock);
+ timer_sleep (25 * TIMER_FREQ);
+
+ msg ("Main thread spinning for 5 seconds...");
+ start_time = timer_ticks ();
+ while (timer_elapsed (start_time) < 5 * TIMER_FREQ)
+ continue;
+
+ msg ("Main thread releasing lock.");
+ lock_release (&lock);
+
+ msg ("Block thread should have already acquired lock.");
+}
+
+static void
+block_thread (void *lock_)
+{
+ struct lock *lock = lock_;
+ int64_t start_time;
+
+ msg ("Block thread spinning for 20 seconds...");
+ start_time = timer_ticks ();
+ while (timer_elapsed (start_time) < 20 * TIMER_FREQ)
+ continue;
+
+ msg ("Block thread acquiring lock...");
+ lock_acquire (lock);
+
+ msg ("...got it.");
+}
--- /dev/null
+# -*- perl -*-
+use strict;
+use warnings;
+use tests::tests;
+check_expected ([<<'EOF']);
+(mlfqs-block) begin
+(mlfqs-block) Main thread acquiring lock.
+(mlfqs-block) Main thread creating block thread, sleeping 25 seconds...
+(mlfqs-block) Block thread spinning for 20 seconds...
+(mlfqs-block) Block thread acquiring lock...
+(mlfqs-block) Main thread spinning for 5 seconds...
+(mlfqs-block) Main thread releasing lock.
+(mlfqs-block) ...got it.
+(mlfqs-block) Block thread should have already acquired lock.
+(mlfqs-block) end
+EOF
{"mlfqs-fair-20", test_mlfqs_fair_20},
{"mlfqs-nice-2", test_mlfqs_nice_2},
{"mlfqs-nice-10", test_mlfqs_nice_10},
+ {"mlfqs-block", test_mlfqs_block},
};
static const char *test_name;
extern test_func test_mlfqs_fair_20;
extern test_func test_mlfqs_nice_2;
extern test_func test_mlfqs_nice_10;
+extern test_func test_mlfqs_block;
void msg (const char *, ...);
void fail (const char *, ...);