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