summaryrefslogtreecommitdiffstats
path: root/src/tests/threads/priority-fifo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/threads/priority-fifo.c')
-rw-r--r--src/tests/threads/priority-fifo.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/tests/threads/priority-fifo.c b/src/tests/threads/priority-fifo.c
new file mode 100644
index 0000000..3af98a3
--- /dev/null
+++ b/src/tests/threads/priority-fifo.c
@@ -0,0 +1,99 @@
+/* Creates several threads all at the same priority and ensures
+ that they consistently run in the same round-robin order.
+
+ Based on a test originally submitted for Stanford's CS 140 in
+ winter 1999 by by Matt Franklin
+ <startled@leland.stanford.edu>, Greg Hutchins
+ <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
+ Modified by arens. */
+
+#include <stdio.h>
+#include "tests/threads/tests.h"
+#include "threads/init.h"
+#include "devices/timer.h"
+#include "threads/malloc.h"
+#include "threads/synch.h"
+#include "threads/thread.h"
+
+struct simple_thread_data
+ {
+ int id; /* Sleeper ID. */
+ int iterations; /* Iterations so far. */
+ struct lock *lock; /* Lock on output. */
+ int **op; /* Output buffer position. */
+ };
+
+#define THREAD_CNT 16
+#define ITER_CNT 16
+
+static thread_func simple_thread_func;
+
+void
+test_priority_fifo (void)
+{
+ struct simple_thread_data data[THREAD_CNT];
+ struct lock lock;
+ int *output, *op;
+ int i, cnt;
+
+ /* This test does not work with the MLFQS. */
+ ASSERT (!thread_mlfqs);
+
+ /* Make sure our priority is the default. */
+ ASSERT (thread_get_priority () == PRI_DEFAULT);
+
+ msg ("%d threads will iterate %d times in the same order each time.",
+ THREAD_CNT, ITER_CNT);
+ msg ("If the order varies then there is a bug.");
+
+ output = op = malloc (sizeof *output * THREAD_CNT * ITER_CNT * 2);
+ ASSERT (output != NULL);
+ lock_init (&lock);
+
+ thread_set_priority (PRI_DEFAULT + 2);
+ for (i = 0; i < THREAD_CNT; i++)
+ {
+ char name[16];
+ struct simple_thread_data *d = data + i;
+ snprintf (name, sizeof name, "%d", i);
+ d->id = i;
+ d->iterations = 0;
+ d->lock = &lock;
+ d->op = &op;
+ thread_create (name, PRI_DEFAULT + 1, simple_thread_func, d);
+ }
+
+ thread_set_priority (PRI_DEFAULT);
+ /* All the other threads now run to termination here. */
+ ASSERT (lock.holder == NULL);
+
+ cnt = 0;
+ for (; output < op; output++)
+ {
+ struct simple_thread_data *d;
+
+ ASSERT (*output >= 0 && *output < THREAD_CNT);
+ d = data + *output;
+ if (cnt % THREAD_CNT == 0)
+ printf ("(priority-fifo) iteration:");
+ printf (" %d", d->id);
+ if (++cnt % THREAD_CNT == 0)
+ printf ("\n");
+ d->iterations++;
+ }
+}
+
+static void
+simple_thread_func (void *data_)
+{
+ struct simple_thread_data *data = data_;
+ int i;
+
+ for (i = 0; i < ITER_CNT; i++)
+ {
+ lock_acquire (data->lock);
+ *(*data->op)++ = data->id;
+ lock_release (data->lock);
+ thread_yield ();
+ }
+}