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