8acef92209075527852d4696c97100204f6fa93a
[pintos-anon] / grading / threads / alarm-single.c
1 /* Problem 1-1: Alarm Clock tests.
2
3    Based on a test originally submitted for Stanford's CS 140 in
4    winter 1998 by Rob Baesman <rbaesman@cs.stanford.edu>, Ben
5    Taskar <btaskar@cs.stanford.edu>, and Toli Kuznets
6    <tolik@cs.stanford.edu>. */
7
8 #include "threads/test.h"
9 #include <stdio.h>
10 #include "threads/malloc.h"
11 #include "threads/synch.h"
12 #include "threads/thread.h"
13 #include "devices/timer.h"
14
15 #ifdef MLFQS
16 #error This test not applicable with MLFQS enabled.
17 #endif
18
19 static void test_sleep (int iterations);
20
21 void
22 test (void) 
23 {
24   test_sleep (1);
25 }
26
27 struct sleep_thread_data 
28   {
29     int64_t start;              /* Start time. */
30     int duration;               /* Number of ticks to sleep. */
31     int iterations;             /* Number of iterations to run. */
32     struct semaphore done;      /* Completion semaphore. */
33     tid_t tid;                  /* Thread ID. */
34     int id;                     /* Sleeper ID. */
35
36     struct lock *lock;          /* Lock on access to `op'. */
37     int **op;                   /* Output buffer position. */
38   };
39
40 static void sleeper (void *);
41
42 static void
43 test_sleep (int iterations) 
44 {
45   struct sleep_thread_data threads[5];
46   const int thread_cnt = sizeof threads / sizeof *threads;
47   int *output, *op;
48   struct lock lock;
49   int64_t start;
50   int product;
51   int i;
52
53   printf ("\n"
54           "Testing %d sleeps per thread.\n"
55           "If successful, product of iteration count and\n"
56           "sleep duration will appear in nondescending order.\n",
57           iterations);
58
59   /* Start all the threads. */
60   product = 0;
61   lock_init (&lock, "product");
62   op = output = malloc (sizeof *output * iterations * thread_cnt * 2);
63   ASSERT (output != NULL);
64   start = timer_ticks ();
65   for (i = 0; i < thread_cnt; i++)
66     {
67       struct sleep_thread_data *t;
68       char name[16];
69       
70       snprintf (name, sizeof name, "thread %d", i);
71       t = threads + i;
72       t->start = start;
73       t->duration = (i + 1) * 10;
74       t->iterations = iterations;
75       sema_init (&t->done, 0, name);
76       t->tid = thread_create (name, PRI_DEFAULT, sleeper, t);
77       t->id = i;
78
79       t->lock = &lock;
80       t->op = &op;
81     }
82   
83   /* Wait for all the threads to finish. */
84   for (i = 0; i < thread_cnt; i++) 
85     {
86       sema_down (&threads[i].done);
87       threads[i].iterations = 1;
88     }
89
90   /* Print output buffer. */
91   product = 0;
92   for (; output < op; output++) 
93     {
94       struct sleep_thread_data *t;
95       int new_prod;
96       
97       ASSERT (*output >= 0 && *output < thread_cnt);
98       t = threads + *output;
99
100       new_prod = t->iterations++ * t->duration;
101         
102       printf ("thread %d: duration=%d, iteration=%d, product=%d\n",
103               t->id, t->duration, t->iterations, new_prod);
104           
105       if (new_prod >= product)
106         product = new_prod;
107       else
108         printf ("thread %d: Out of order sleep completion (%d > %d)!\n",
109                 t->id, product, new_prod);
110     }
111   
112   printf ("...done\n");
113 }
114
115 static void
116 sleeper (void *t_) 
117 {
118   struct sleep_thread_data *t = t_;
119   int i;
120
121   for (i = 1; i <= t->iterations; i++) 
122     {
123       timer_sleep ((t->start + i * t->duration) - timer_ticks ());
124
125       lock_acquire (t->lock);
126       *(*t->op)++ = t->id;
127       lock_release (t->lock);
128     }
129   
130   /* Signal completion. */
131   sema_up (&t->done);
132 }