01cc7a7737071f2878c818aad360bf6948d700e5
[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 #include "threads/test.h"
10 #include <stdio.h>
11 #include "devices/timer.h"
12 #include "threads/malloc.h"
13 #include "threads/synch.h"
14 #include "threads/thread.h"
15
16 static void test_fifo (void);
17
18 void
19 test (void) 
20 {
21   /* This test does not work with the MLFQS. */
22   ASSERT (!enable_mlfqs);
23
24   /* Make sure our priority is the default. */
25   ASSERT (thread_get_priority () == PRI_DEFAULT);
26
27   test_fifo ();
28 }
29 \f
30 static thread_func simple_thread_func;
31
32 struct simple_thread_data 
33   {
34     int id;                     /* Sleeper ID. */
35     int iterations;             /* Iterations so far. */
36     struct lock *lock;          /* Lock on output. */
37     int **op;                   /* Output buffer position. */
38   };
39
40 #define THREAD_CNT 10
41 #define ITER_CNT 5
42
43 static void
44 test_fifo (void) 
45 {
46   struct simple_thread_data data[THREAD_CNT];
47   struct lock lock;
48   int *output, *op;
49   int i;
50   
51   printf ("\n"
52           "Testing FIFO preemption.\n"
53           "%d threads will iterate %d times in the same order each time.\n"
54           "If the order varies then there is a bug.\n",
55           THREAD_CNT, ITER_CNT);
56
57   output = op = malloc (sizeof *output * THREAD_CNT * ITER_CNT * 2);
58   ASSERT (output != NULL);
59   lock_init (&lock, "output");
60
61   thread_set_priority (PRI_DEFAULT + 2);
62   for (i = 0; i < THREAD_CNT; i++) 
63     {
64       char name[16];
65       struct simple_thread_data *d = data + i;
66       snprintf (name, sizeof name, "%d", i);
67       d->id = i;
68       d->iterations = 0;
69       d->lock = &lock;
70       d->op = &op;
71       thread_create (name, PRI_DEFAULT + 1, simple_thread_func, d);
72     }
73
74   /* This should ensure that the iterations start at the
75      beginning of a timer tick. */
76   timer_sleep (10);
77   thread_set_priority (PRI_DEFAULT);
78
79   lock_acquire (&lock);
80   for (; output < op; output++) 
81     {
82       struct simple_thread_data *d;
83
84       ASSERT (*output >= 0 && *output < THREAD_CNT);
85       d = data + *output;
86       if (d->iterations != ITER_CNT)
87         printf ("Thread %d iteration %d\n", d->id, d->iterations);
88       else
89         printf ("Thread %d done!\n", d->id);
90       d->iterations++;
91     }
92   printf ("FIFO preemption test done.\n");
93   lock_release (&lock);
94 }
95
96 static void 
97 simple_thread_func (void *data_) 
98 {
99   struct simple_thread_data *data = data_;
100   int i;
101   
102   for (i = 0; i <= ITER_CNT; i++) 
103     {
104       lock_acquire (data->lock);
105       *(*data->op)++ = data->id;
106       lock_release (data->lock);
107       thread_yield ();
108     }
109 }