On newer systems -ltinfo needs to be explicitly added to the link flags
[pintos-anon] / src / tests / threads / mlfqs-fair.c
1 /* Measures the correctness of the "nice" implementation.
2
3    The "fair" tests run either 2 or 20 threads all niced to 0.
4    The threads should all receive approximately the same number
5    of ticks.  Each test runs for 30 seconds, so the ticks should
6    also sum to approximately 30 * 100 == 3000 ticks.
7
8    The mlfqs-nice-2 test runs 2 threads, one with nice 0, the
9    other with nice 5, which should receive 1,904 and 1,096 ticks,
10    respectively, over 30 seconds.
11
12    The mlfqs-nice-10 test runs 10 threads with nice 0 through 9.
13    They should receive 672, 588, 492, 408, 316, 232, 152, 92, 40,
14    and 8 ticks, respectively, over 30 seconds.
15
16    (The above are computed via simulation in mlfqs.pm.) */
17
18 #include <stdio.h>
19 #include <inttypes.h>
20 #include "tests/threads/tests.h"
21 #include "threads/init.h"
22 #include "threads/malloc.h"
23 #include "threads/palloc.h"
24 #include "threads/synch.h"
25 #include "threads/thread.h"
26 #include "devices/timer.h"
27
28 static void test_mlfqs_fair (int thread_cnt, int nice_min, int nice_step);
29
30 void
31 test_mlfqs_fair_2 (void) 
32 {
33   test_mlfqs_fair (2, 0, 0);
34 }
35
36 void
37 test_mlfqs_fair_20 (void) 
38 {
39   test_mlfqs_fair (20, 0, 0);
40 }
41
42 void
43 test_mlfqs_nice_2 (void) 
44 {
45   test_mlfqs_fair (2, 0, 5);
46 }
47
48 void
49 test_mlfqs_nice_10 (void) 
50 {
51   test_mlfqs_fair (10, 0, 1);
52 }
53 \f
54 #define MAX_THREAD_CNT 20
55
56 struct thread_info 
57   {
58     int64_t start_time;
59     int tick_count;
60     int nice;
61   };
62
63 static void load_thread (void *aux);
64
65 static void
66 test_mlfqs_fair (int thread_cnt, int nice_min, int nice_step)
67 {
68   struct thread_info info[MAX_THREAD_CNT];
69   int64_t start_time;
70   int nice;
71   int i;
72
73   ASSERT (thread_mlfqs);
74   ASSERT (thread_cnt <= MAX_THREAD_CNT);
75   ASSERT (nice_min >= -10);
76   ASSERT (nice_step >= 0);
77   ASSERT (nice_min + nice_step * (thread_cnt - 1) <= 20);
78
79   thread_set_nice (-20);
80
81   start_time = timer_ticks ();
82   msg ("Starting %d threads...", thread_cnt);
83   nice = nice_min;
84   for (i = 0; i < thread_cnt; i++) 
85     {
86       struct thread_info *ti = &info[i];
87       char name[16];
88
89       ti->start_time = start_time;
90       ti->tick_count = 0;
91       ti->nice = nice;
92
93       snprintf(name, sizeof name, "load %d", i);
94       thread_create (name, PRI_DEFAULT, load_thread, ti);
95
96       nice += nice_step;
97     }
98   msg ("Starting threads took %"PRId64" ticks.", timer_elapsed (start_time));
99
100   msg ("Sleeping 40 seconds to let threads run, please wait...");
101   timer_sleep (40 * TIMER_FREQ);
102   
103   for (i = 0; i < thread_cnt; i++)
104     msg ("Thread %d received %d ticks.", i, info[i].tick_count);
105 }
106
107 static void
108 load_thread (void *ti_) 
109 {
110   struct thread_info *ti = ti_;
111   int64_t sleep_time = 5 * TIMER_FREQ;
112   int64_t spin_time = sleep_time + 30 * TIMER_FREQ;
113   int64_t last_time = 0;
114
115   thread_set_nice (ti->nice);
116   timer_sleep (sleep_time - timer_elapsed (ti->start_time));
117   while (timer_elapsed (ti->start_time) < spin_time) 
118     {
119       int64_t cur_time = timer_ticks ();
120       if (cur_time != last_time)
121         ti->tick_count++;
122       last_time = cur_time;
123     }
124 }