124 lines
2.9 KiB
C
Executable file
124 lines
2.9 KiB
C
Executable file
/* Measures the correctness of the "nice" implementation.
|
||
|
||
The "fair" tests run either 2 or 20 threads all niced to 0.
|
||
The threads should all receive approximately the same number
|
||
of ticks. Each test runs for 30 seconds, so the ticks should
|
||
also sum to approximately 30 * 100 == 3000 ticks.
|
||
|
||
The mlfqs-nice-2 test runs 2 threads, one with nice 0, the
|
||
other with nice 5, which should receive 1,904 and 1,096 ticks,
|
||
respectively, over 30 seconds.
|
||
|
||
The mlfqs-nice-10 test runs 10 threads with nice 0 through 9.
|
||
They should receive 672, 588, 492, 408, 316, 232, 152, 92, 40,
|
||
and 8 ticks, respectively, over 30 seconds.
|
||
|
||
(The above are computed via simulation in mlfqs.pm.) */
|
||
|
||
#include <stdio.h>
|
||
#include <inttypes.h>
|
||
#include "tests/threads/tests.h"
|
||
#include "threads/init.h"
|
||
#include "threads/malloc.h"
|
||
#include "threads/palloc.h"
|
||
#include "threads/synch.h"
|
||
#include "threads/thread.h"
|
||
#include "devices/timer.h"
|
||
|
||
static void test_mlfqs_fair (int thread_cnt, int nice_min, int nice_step);
|
||
|
||
void
|
||
test_mlfqs_fair_2 (void)
|
||
{
|
||
test_mlfqs_fair (2, 0, 0);
|
||
}
|
||
|
||
void
|
||
test_mlfqs_fair_20 (void)
|
||
{
|
||
test_mlfqs_fair (20, 0, 0);
|
||
}
|
||
|
||
void
|
||
test_mlfqs_nice_2 (void)
|
||
{
|
||
test_mlfqs_fair (2, 0, 5);
|
||
}
|
||
|
||
void
|
||
test_mlfqs_nice_10 (void)
|
||
{
|
||
test_mlfqs_fair (10, 0, 1);
|
||
}
|
||
|
||
#define MAX_THREAD_CNT 20
|
||
|
||
struct thread_info
|
||
{
|
||
int64_t start_time;
|
||
int tick_count;
|
||
int nice;
|
||
};
|
||
|
||
static void load_thread (void *aux);
|
||
|
||
static void
|
||
test_mlfqs_fair (int thread_cnt, int nice_min, int nice_step)
|
||
{
|
||
struct thread_info info[MAX_THREAD_CNT];
|
||
int64_t start_time;
|
||
int nice;
|
||
int i;
|
||
|
||
ASSERT (thread_mlfqs);
|
||
ASSERT (thread_cnt <= MAX_THREAD_CNT);
|
||
ASSERT (nice_min >= -10);
|
||
ASSERT (nice_step >= 0);
|
||
ASSERT (nice_min + nice_step * (thread_cnt - 1) <= 20);
|
||
|
||
thread_set_nice (-20);
|
||
|
||
start_time = timer_ticks ();
|
||
msg ("Starting %d threads...", thread_cnt);
|
||
nice = nice_min;
|
||
for (i = 0; i < thread_cnt; i++)
|
||
{
|
||
struct thread_info *ti = &info[i];
|
||
char name[16];
|
||
|
||
ti->start_time = start_time;
|
||
ti->tick_count = 0;
|
||
ti->nice = nice;
|
||
|
||
snprintf(name, sizeof name, "load %d", i);
|
||
thread_create (name, PRI_DEFAULT, load_thread, ti);
|
||
|
||
nice += nice_step;
|
||
}
|
||
msg ("Starting threads took %"PRId64" ticks.", timer_elapsed (start_time));
|
||
|
||
msg ("Sleeping 40 seconds to let threads run, please wait...");
|
||
timer_sleep (40 * TIMER_FREQ);
|
||
|
||
for (i = 0; i < thread_cnt; i++)
|
||
msg ("Thread %d received %d ticks.", i, info[i].tick_count);
|
||
}
|
||
|
||
static void
|
||
load_thread (void *ti_)
|
||
{
|
||
struct thread_info *ti = ti_;
|
||
int64_t sleep_time = 5 * TIMER_FREQ;
|
||
int64_t spin_time = sleep_time + 30 * TIMER_FREQ;
|
||
int64_t last_time = 0;
|
||
|
||
thread_set_nice (ti->nice);
|
||
timer_sleep (sleep_time - timer_elapsed (ti->start_time));
|
||
while (timer_elapsed (ti->start_time) < spin_time)
|
||
{
|
||
int64_t cur_time = timer_ticks ();
|
||
if (cur_time != last_time)
|
||
ti->tick_count++;
|
||
last_time = cur_time;
|
||
}
|
||
}
|