Move THREAD_JOIN_IMPLEMENTED to constants.h.
[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 #include "threads/test.h"
14 #include <stdio.h>
15 #include "threads/synch.h"
16 #include "threads/thread.h"
17 #include "devices/timer.h"
18
19 static void test_sleep (int iterations);
20
21 void
22 test (void) 
23 {
24   test_sleep (1);
25   test_sleep (7);
26 }
27
28 struct sleep_thread_data 
29   {
30     int64_t start;              /* Start time. */
31     int duration;               /* Number of ticks to sleep. */
32     int iterations;             /* Number of iterations to run. */
33     int *product;               /* Largest product so far. */
34     struct lock *lock;          /* Lock on access to `product'. */
35     struct semaphore done;      /* Completion semaphore. */
36     tid_t tid;                  /* Thread ID. */
37   };
38
39 static void sleeper (void *);
40
41 static void
42 test_sleep (int iterations) 
43 {
44   struct sleep_thread_data threads[5];
45   const int thread_cnt = sizeof threads / sizeof *threads;
46   struct lock lock;
47   int64_t start;
48   int product;
49   int i;
50
51   printf ("\n"
52           "Testing %d sleeps per thread.\n"
53           "If successful, product of iteration count and\n"
54           "sleep duration will appear in nondescending order.\n",
55           iterations);
56
57   /* Start all the threads. */
58   product = 0;
59   lock_init (&lock, "product");
60   start = timer_ticks ();
61   for (i = 0; i < thread_cnt; i++)
62     {
63       struct sleep_thread_data *t;
64       char name[16];
65       
66       snprintf (name, sizeof name, "thread %d", i);
67       t = threads + i;
68       t->start = start;
69       t->duration = (i + 1) * 10;
70       t->iterations = iterations;
71       t->product = &product;
72       t->lock = &lock;
73       sema_init (&t->done, 0, name);
74       t->tid = thread_create (name, PRI_DEFAULT, sleeper, t);
75     }
76   
77   /* Wait for all the threads to finish. */
78   for (i = 0; i < thread_cnt; i++) 
79     {
80 #ifdef THREAD_JOIN_IMPLEMENTED
81       thread_join (threads[i].tid);
82 #else
83       sema_down (&threads[i].done);
84 #endif
85     }
86
87   printf ("...done\n");
88 }
89
90 static void
91 sleeper (void *t_) 
92 {
93   struct sleep_thread_data *t = t_;
94   int i;
95
96   for (i = 1; i <= t->iterations; i++) 
97     {
98       int old_product;
99       int new_product = i * t->duration;
100
101       timer_sleep ((t->start + new_product) - timer_ticks ());
102
103       lock_acquire (t->lock);
104       old_product = *t->product;
105       *t->product = new_product;
106       lock_release (t->lock);
107
108       printf ("%s: duration=%d, iteration=%d, product=%d\n",
109               thread_name (), t->duration, i, new_product);
110
111       if (old_product > new_product)
112         printf ("%s: Out of order sleep completion (%d > %d)!\n",
113                 thread_name (), old_product, new_product);
114     }
115   
116   /* Signal completion. */
117   sema_up (&t->done);
118 }