2f891962ad4e0a796bdc1851da970c27c93af7dd
[pintos-anon] / src / tests / threads / priority-fifo.c
1 /* Creates several threads all at the same priority and ensures
2    that they consistently run in the same round-robin order.
3
4    Based on a test originally submitted for Stanford's CS 140 in
5    winter 1999 by by Matt Franklin
6    <startled@leland.stanford.edu>, Greg Hutchins
7    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
8    Modified by arens. */
9
10 #include <stdio.h>
11 #include "tests/threads/tests.h"
12 #include "threads/init.h"
13 #include "devices/timer.h"
14 #include "threads/malloc.h"
15 #include "threads/synch.h"
16 #include "threads/thread.h"
17
18 struct simple_thread_data 
19   {
20     int id;                     /* Sleeper ID. */
21     int iterations;             /* Iterations so far. */
22     struct lock *lock;          /* Lock on output. */
23     int **op;                   /* Output buffer position. */
24   };
25
26 #define THREAD_CNT 16
27 #define ITER_CNT 16
28
29 static thread_func simple_thread_func;
30
31 void
32 test_priority_fifo (void) 
33 {
34   struct simple_thread_data data[THREAD_CNT];
35   struct lock lock;
36   int *output, *op;
37   int i, cnt;
38
39   /* This test does not work with the MLFQS. */
40   ASSERT (!enable_mlfqs);
41
42   /* Make sure our priority is the default. */
43   ASSERT (thread_get_priority () == PRI_DEFAULT);
44
45   msg ("%d threads will iterate %d times in the same order each time.",
46        THREAD_CNT, ITER_CNT);
47   msg ("If the order varies then there is a bug.");
48
49   output = op = malloc (sizeof *output * THREAD_CNT * ITER_CNT * 2);
50   ASSERT (output != NULL);
51   lock_init (&lock);
52
53   thread_set_priority (PRI_DEFAULT + 2);
54   for (i = 0; i < THREAD_CNT; i++) 
55     {
56       char name[16];
57       struct simple_thread_data *d = data + i;
58       snprintf (name, sizeof name, "%d", i);
59       d->id = i;
60       d->iterations = 0;
61       d->lock = &lock;
62       d->op = &op;
63       thread_create (name, PRI_DEFAULT + 1, simple_thread_func, d);
64     }
65
66   thread_set_priority (PRI_DEFAULT);
67   /* All the other threads now run to termination here. */
68   ASSERT (lock.holder == NULL);
69
70   cnt = 0;
71   for (; output < op; output++) 
72     {
73       struct simple_thread_data *d;
74
75       ASSERT (*output >= 0 && *output < THREAD_CNT);
76       d = data + *output;
77       if (cnt % THREAD_CNT == 0)
78         printf ("(priority-fifo) iteration:");
79       printf (" %d", d->id);
80       if (++cnt % THREAD_CNT == 0)
81         printf ("\n");
82       d->iterations++;
83     }
84 }
85
86 static void 
87 simple_thread_func (void *data_) 
88 {
89   struct simple_thread_data *data = data_;
90   int i;
91   
92   for (i = 0; i < ITER_CNT; i++) 
93     {
94       lock_acquire (data->lock);
95       *(*data->op)++ = data->id;
96       lock_release (data->lock);
97       thread_yield ();
98     }
99 }