100 lines
2.5 KiB
C
100 lines
2.5 KiB
C
|
/* 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 ();
|
||
|
}
|
||
|
}
|