4ba3651f44cba4a3fca97bd6f7fe7915b286568f
[pintos-anon] / src / tests / threads / alarm-simultaneous.c
1 /* Creates N threads, each of which sleeps a different, fixed
2    duration, M times.  Records the wake-up order and verifies
3    that it is valid. */
4
5 #include <stdio.h>
6 #include "tests/threads/tests.h"
7 #include "threads/init.h"
8 #include "threads/malloc.h"
9 #include "threads/synch.h"
10 #include "threads/thread.h"
11 #include "devices/timer.h"
12
13 static void test_sleep (int thread_cnt, int iterations);
14
15 void
16 test_alarm_simultaneous (void) 
17 {
18   test_sleep (3, 5);
19 }
20
21 /* Information about the test. */
22 struct sleep_test 
23   {
24     int64_t start;              /* Current time at start of test. */
25     int iterations;             /* Number of iterations per thread. */
26     int *output_pos;            /* Current position in output buffer. */
27   };
28
29 static void sleeper (void *);
30
31 /* Runs THREAD_CNT threads thread sleep ITERATIONS times each. */
32 static void
33 test_sleep (int thread_cnt, int iterations) 
34 {
35   struct sleep_test test;
36   int *output;
37   int i;
38
39   /* This test does not work with the MLFQS. */
40   ASSERT (!enable_mlfqs);
41
42   msg ("Creating %d threads to sleep %d times each.", thread_cnt, iterations);
43   msg ("Each thread sleeps 10 ticks each time.");
44   msg ("Within an iteration, all threads should wake up on the same tick.");
45
46   /* Allocate memory. */
47   output = malloc (sizeof *output * iterations * thread_cnt * 2);
48   if (output == NULL)
49     PANIC ("couldn't allocate memory for test");
50
51   /* Initialize test. */
52   test.start = timer_ticks () + 100;
53   test.iterations = iterations;
54   test.output_pos = output;
55
56   /* Start threads. */
57   ASSERT (output != NULL);
58   for (i = 0; i < thread_cnt; i++)
59     {
60       char name[16];
61       snprintf (name, sizeof name, "thread %d", i);
62       thread_create (name, PRI_DEFAULT, sleeper, &test);
63     }
64   
65   /* Wait long enough for all the threads to finish. */
66   timer_sleep (100 + iterations * 10 + 100);
67
68   /* Print completion order. */
69   msg ("iteration 0, thread 0: woke up after %d ticks", output[0]);
70   for (i = 1; i < test.output_pos - output; i++) 
71     msg ("iteration %d, thread %d: woke up %d ticks later",
72          i / thread_cnt, i % thread_cnt, output[i] - output[i - 1]);
73   
74   free (output);
75 }
76
77 /* Sleeper thread. */
78 static void
79 sleeper (void *test_) 
80 {
81   struct sleep_test *test = test_;
82   int i;
83
84   /* Make sure we're at the beginning of a timer tick. */
85   timer_sleep (1);
86
87   for (i = 1; i <= test->iterations; i++) 
88     {
89       int64_t sleep_until = test->start + i * 10;
90       timer_sleep (sleep_until - timer_ticks ());
91       *test->output_pos++ = timer_ticks () - test->start;
92       thread_yield ();
93     }
94 }