CS318 - Pintos
Pintos source browser for JHU CS318 course
alarm-wait.c
Go to the documentation of this file.
1 /** Creates N threads, each of which sleeps a different, fixed
2  duration, M times. Records the wake-up order and verifies
3  that it is valid. */
4 
5 #include <stdio.h>
6 #include "tests/threads/tests.h"
7 #include "threads/init.h"
8 #include "threads/malloc.h"
9 #include "threads/synch.h"
10 #include "threads/thread.h"
11 #include "devices/timer.h"
12 
13 static void test_sleep (int thread_cnt, int iterations);
14 
15 void
17 {
18  test_sleep (5, 1);
19 }
20 
21 void
23 {
24  test_sleep (5, 7);
25 }
26 
27 /** Information about the test. */
28 struct sleep_test
29  {
30  int64_t start; /**< Current time at start of test. */
31  int iterations; /**< Number of iterations per thread. */
32 
33  /* Output. */
34  struct lock output_lock; /**< Lock protecting output buffer. */
35  int *output_pos; /**< Current position in output buffer. */
36  };
37 
38 /** Information about an individual thread in the test. */
39 struct sleep_thread
40  {
41  struct sleep_test *test; /**< Info shared between all threads. */
42  int id; /**< Sleeper ID. */
43  int duration; /**< Number of ticks to sleep. */
44  int iterations; /**< Iterations counted so far. */
45  };
46 
47 static void sleeper (void *);
48 
49 /** Runs THREAD_CNT threads thread sleep ITERATIONS times each. */
50 static void
51 test_sleep (int thread_cnt, int iterations)
52 {
53  struct sleep_test test;
54  struct sleep_thread *threads;
55  int *output, *op;
56  int product;
57  int i;
58 
59  /* This test does not work with the MLFQS. */
61 
62  msg ("Creating %d threads to sleep %d times each.", thread_cnt, iterations);
63  msg ("Thread 0 sleeps 10 ticks each time,");
64  msg ("thread 1 sleeps 20 ticks each time, and so on.");
65  msg ("If successful, product of iteration count and");
66  msg ("sleep duration will appear in nondescending order.");
67 
68  /* Allocate memory. */
69  threads = malloc (sizeof *threads * thread_cnt);
70  output = malloc (sizeof *output * iterations * thread_cnt * 2);
71  if (threads == NULL || output == NULL)
72  PANIC ("couldn't allocate memory for test");
73 
74  /* Initialize test. */
75  test.start = timer_ticks () + 100;
76  test.iterations = iterations;
77  lock_init (&test.output_lock);
78  test.output_pos = output;
79 
80  /* Start threads. */
81  ASSERT (output != NULL);
82  for (i = 0; i < thread_cnt; i++)
83  {
84  struct sleep_thread *t = threads + i;
85  char name[16];
86 
87  t->test = &test;
88  t->id = i;
89  t->duration = (i + 1) * 10;
90  t->iterations = 0;
91 
92  snprintf (name, sizeof name, "thread %d", i);
94  }
95 
96  /* Wait long enough for all the threads to finish. */
97  timer_sleep (100 + thread_cnt * iterations * 10 + 100);
98 
99  /* Acquire the output lock in case some rogue thread is still
100  running. */
101  lock_acquire (&test.output_lock);
102 
103  /* Print completion order. */
104  product = 0;
105  for (op = output; op < test.output_pos; op++)
106  {
107  struct sleep_thread *t;
108  int new_prod;
109 
110  ASSERT (*op >= 0 && *op < thread_cnt);
111  t = threads + *op;
112 
113  new_prod = ++t->iterations * t->duration;
114 
115  msg ("thread %d: duration=%d, iteration=%d, product=%d",
116  t->id, t->duration, t->iterations, new_prod);
117 
118  if (new_prod >= product)
119  product = new_prod;
120  else
121  fail ("thread %d woke up out of order (%d > %d)!",
122  t->id, product, new_prod);
123  }
124 
125  /* Verify that we had the proper number of wakeups. */
126  for (i = 0; i < thread_cnt; i++)
127  if (threads[i].iterations != iterations)
128  fail ("thread %d woke up %d times instead of %d",
129  i, threads[i].iterations, iterations);
130 
131  lock_release (&test.output_lock);
132  free (output);
133  free (threads);
134 }
135 
136 /** Sleeper thread. */
137 static void
138 sleeper (void *t_)
139 {
140  struct sleep_thread *t = t_;
141  struct sleep_test *test = t->test;
142  int i;
143 
144  for (i = 1; i <= test->iterations; i++)
145  {
146  int64_t sleep_until = test->start + i * t->duration;
147  timer_sleep (sleep_until - timer_ticks ());
148  lock_acquire (&test->output_lock);
149  *test->output_pos++ = t->id;
150  lock_release (&test->output_lock);
151  }
152 }
name
char * name[]
Definition: insult.c:47
malloc
void * malloc(size_t size)
Obtains and returns a new block of at least SIZE bytes.
Definition: malloc.c:90
snprintf
int snprintf(char *buffer, size_t buf_size, const char *format,...)
Like printf(), except that output is stored into BUFFER, which must have space for BUF_SIZE character...
Definition: stdio.c:62
lock_release
void lock_release(struct lock *lock)
Releases LOCK, which must be owned by the current thread.
Definition: synch.c:229
NULL
#define NULL
Definition: stddef.h:4
test
Definition: tests.c:6
lock_init
void lock_init(struct lock *lock)
Initializes LOCK.
Definition: synch.c:176
free
void free(void *p)
Frees block P, which must have been previously allocated with malloc(), calloc(), or realloc().
Definition: malloc.c:219
PANIC
#define PANIC(...)
Halts the OS, printing the source file name, line number, and function name, plus a user-specific mes...
Definition: debug.h:14
sleep_thread::test
struct sleep_test * test
Info shared between all threads.
Definition: alarm-wait.c:41
int64_t
signed long long int int64_t
Definition: stdint.h:16
test_alarm_multiple
void test_alarm_multiple(void)
Definition: alarm-wait.c:22
init.h
sleep_test::output_pos
int * output_pos
Current position in output buffer.
Definition: alarm-simultaneous.c:26
timer.h
sleeper
static void sleeper(void *)
Sleeper thread.
Definition: alarm-wait.c:138
test
void test(void)
Test the linked list implementation.
Definition: list.c:36
timer_sleep
void timer_sleep(int64_t ticks)
Sleeps for approximately TICKS timer ticks.
Definition: timer.c:90
sleep_thread::id
int id
Sleeper ID.
Definition: alarm-wait.c:42
malloc.h
timer_ticks
int64_t timer_ticks(void)
Returns the number of timer ticks since the OS booted.
Definition: timer.c:71
ASSERT
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
fail
void fail(const char *format,...)
Definition: lib.c:40
sleep_test::start
int64_t start
Current time at start of test.
Definition: alarm-simultaneous.c:24
sleep_test::iterations
int iterations
Number of iterations per thread.
Definition: alarm-simultaneous.c:25
sleep_test::output_lock
struct lock output_lock
Lock protecting output buffer.
Definition: alarm-wait.c:34
msg
void msg(const char *format,...)
Definition: lib.c:28
sleep_thread::iterations
int iterations
Iterations counted so far.
Definition: alarm-wait.c:44
thread_mlfqs
bool thread_mlfqs
If false (default), use round-robin scheduler.
Definition: thread.c:60
thread_create
tid_t thread_create(const char *name, int priority, thread_func *function, void *aux)
Creates a new kernel thread named NAME with the given initial PRIORITY, which executes FUNCTION passi...
Definition: thread.c:166
tests.h
test_alarm_single
void test_alarm_single(void)
Definition: alarm-wait.c:16
test_sleep
static void test_sleep(int thread_cnt, int iterations)
Creates N threads, each of which sleeps a different, fixed duration, M times.
Definition: alarm-wait.c:51
lock_acquire
void lock_acquire(struct lock *lock)
Acquires LOCK, sleeping until it becomes available if necessary.
Definition: synch.c:193
sleep_thread
Information about an individual thread in the test.
Definition: alarm-wait.c:39
thread.h
synch.h
lock
Lock.
Definition: synch.h:21
sleep_thread::duration
int duration
Number of ticks to sleep.
Definition: alarm-wait.c:43
PRI_DEFAULT
#define PRI_DEFAULT
Default priority.
Definition: thread.h:24
sleep_test
Information about the test.
Definition: alarm-simultaneous.c:22