6f8fa9b73a21eaff7c16e6a43690f67ab184a0d2
[pintos-anon] / grading / threads / priority-fifo.c
1 /* Problem 1-3: Priority Scheduling tests.
2
3    Based on a test originally submitted for Stanford's CS 140 in
4    winter 1999 by by Matt Franklin
5    <startled@leland.stanford.edu>, Greg Hutchins
6    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
7    Modified by arens. */
8
9 #ifdef MLFQS
10 #error This test not applicable with MLFQS enabled.
11 #endif
12
13 #include "threads/test.h"
14 #include <stdio.h>
15 #include "devices/timer.h"
16 #include "threads/malloc.h"
17 #include "threads/synch.h"
18 #include "threads/thread.h"
19
20 static void test_fifo (void);
21
22 void
23 test (void) 
24 {
25   /* Make sure our priority is the default. */
26   ASSERT (thread_get_priority () == PRI_DEFAULT);
27
28   test_fifo ();
29 }
30 \f
31 static thread_func simple_thread_func;
32
33 struct simple_thread_data 
34   {
35     int id;                     /* Sleeper ID. */
36     int iterations;             /* Iterations so far. */
37     struct lock *lock;          /* Lock on output. */
38     int **op;                   /* Output buffer position. */
39   };
40
41 #define THREAD_CNT 10
42 #define ITER_CNT 5
43
44 static void
45 test_fifo (void) 
46 {
47   struct simple_thread_data data[THREAD_CNT];
48   struct lock lock;
49   int *output, *op;
50   int i;
51   
52   printf ("\n"
53           "Testing FIFO preemption.\n"
54           "%d threads will iterate %d times in the same order each time.\n"
55           "If the order varies then there is a bug.\n",
56           THREAD_CNT, ITER_CNT);
57
58   output = op = malloc (sizeof *output * THREAD_CNT * ITER_CNT * 2);
59   ASSERT (output != NULL);
60   lock_init (&lock, "output");
61
62   thread_set_priority (PRI_DEFAULT + 2);
63   for (i = 0; i < THREAD_CNT; i++) 
64     {
65       char name[16];
66       struct simple_thread_data *d = data + i;
67       snprintf (name, sizeof name, "%d", i);
68       d->id = i;
69       d->iterations = 0;
70       d->lock = &lock;
71       d->op = &op;
72       thread_create (name, PRI_DEFAULT + 1, simple_thread_func, d);
73     }
74
75   /* This should ensure that the iterations start at the
76      beginning of a timer tick. */
77   timer_sleep (10);
78   thread_set_priority (PRI_DEFAULT);
79
80   lock_acquire (&lock);
81   for (; output < op; output++) 
82     {
83       struct simple_thread_data *d;
84
85       ASSERT (*output >= 0 && *output < THREAD_CNT);
86       d = data + *output;
87       if (d->iterations != ITER_CNT)
88         printf ("Thread %d iteration %d\n", d->id, d->iterations);
89       else
90         printf ("Thread %d done!\n", d->id);
91       d->iterations++;
92     }
93   printf ("FIFO preemption test done.\n");
94   lock_release (&lock);
95 }
96
97 static void 
98 simple_thread_func (void *data_) 
99 {
100   struct simple_thread_data *data = data_;
101   int i;
102   
103   for (i = 0; i <= ITER_CNT; i++) 
104     {
105       lock_acquire (data->lock);
106       *(*data->op)++ = data->id;
107       lock_release (data->lock);
108       thread_yield ();
109     }
110 }