7e528668addb5e2735f5b3a16e6d21585852cff6
[pintos-anon] / src / tests / threads / p1-1.c
1 /* Problem 1-1: Alarm Clock tests.
2
3    These tests will work with Pintos "out of the box" because an
4    implementation of timer_sleep() that "busy-waits" is
5    included.  You need to replace that implementation with one
6    that doesn't busy-wait.
7
8    Based on a test originally submitted for Stanford's CS 140 in
9    winter 1998 by Rob Baesman <rbaesman@cs.stanford.edu>, Ben
10    Taskar <btaskar@cs.stanford.edu>, and Toli Kuznets
11    <tolik@cs.stanford.edu>. */
12
13 #ifdef MLFQS
14 #error This test not applicable with MLFQS enabled.
15 #endif
16
17 #include "threads/test.h"
18 #include <stdio.h>
19 #include "threads/synch.h"
20 #include "threads/thread.h"
21 #include "devices/timer.h"
22
23 static void test_sleep (int iterations);
24
25 void
26 test (void) 
27 {
28   test_sleep (1);
29   test_sleep (7);
30 }
31
32 struct sleep_thread_data 
33   {
34     int64_t start;              /* Start time. */
35     int duration;               /* Number of ticks to sleep. */
36     int iterations;             /* Number of iterations to run. */
37     int *product;               /* Largest product so far. */
38     struct lock *lock;          /* Lock on access to `product'. */
39     struct semaphore done;      /* Completion semaphore. */
40     tid_t tid;                  /* Thread ID. */
41   };
42
43 static void sleeper (void *);
44
45 static void
46 test_sleep (int iterations) 
47 {
48   struct sleep_thread_data threads[5];
49   const int thread_cnt = sizeof threads / sizeof *threads;
50   struct lock lock;
51   int64_t start;
52   int product;
53   int i;
54
55   printf ("\n"
56           "Testing %d sleeps per thread.\n"
57           "If successful, product of iteration count and\n"
58           "sleep duration will appear in nondescending order.\n",
59           iterations);
60
61   /* Start all the threads. */
62   product = 0;
63   lock_init (&lock, "product");
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       t->product = &product;
76       t->lock = &lock;
77       sema_init (&t->done, 0, name);
78       t->tid = thread_create (name, PRI_DEFAULT, sleeper, t);
79     }
80   
81   /* Wait for all the threads to finish. */
82   for (i = 0; i < thread_cnt; i++) 
83     {
84 #ifdef THREAD_JOIN_IMPLEMENTED
85       thread_join (threads[i].tid);
86 #else
87       sema_down (&threads[i].done);
88 #endif
89     }
90
91   printf ("...done\n");
92 }
93
94 static void
95 sleeper (void *t_) 
96 {
97   struct sleep_thread_data *t = t_;
98   int i;
99
100   for (i = 1; i <= t->iterations; i++) 
101     {
102       int old_product;
103       int new_product = i * t->duration;
104
105       timer_sleep ((t->start + new_product) - timer_ticks ());
106
107       lock_acquire (t->lock);
108       old_product = *t->product;
109       *t->product = new_product;
110       lock_release (t->lock);
111
112       printf ("%s: duration=%d, iteration=%d, product=%d\n",
113               thread_name (), t->duration, i, new_product);
114
115       if (old_product > new_product)
116         printf ("%s: Out of order sleep completion (%d > %d)!\n",
117                 thread_name (), old_product, new_product);
118     }
119   
120   /* Signal completion. */
121   sema_up (&t->done);
122 }