/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- cleanitems
- inititems
- semtestthread
- semtest
- fail
- locktestthread
- locktest
- cvtestthread
- cvtest
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3 * The President and Fellows of Harvard College.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Synchronization test code.
32 */
33
34 #include <types.h>
35 #include <lib.h>
36 #include <clock.h>
37 #include <thread.h>
38 #include <synch.h>
39 #include <test.h>
40
41 #define NSEMLOOPS 63
42 #define NLOCKLOOPS 120
43 #define NCVLOOPS 5
44 #define NTHREADS 32
45
46 static volatile unsigned long testval1;
47 static volatile unsigned long testval2;
48 static volatile unsigned long testval3;
49 #ifdef UW
50 static struct semaphore *testsem = 0;
51 static struct lock *testlock = 0;
52 static struct cv *testcv = 0;
53 static struct semaphore *donesem = 0;
54 #else
55 static struct semaphore *testsem;
56 static struct lock *testlock;
57 static struct cv *testcv;
58 static struct semaphore *donesem;
59 #endif
60
61 #ifdef UW
62 static
63 void
64 cleanitems(void)
65 {
66 kprintf("cleanitems: Destroying sems, locks, and cvs\n");
67 sem_destroy(testsem);
68 lock_destroy(testlock);
69 cv_destroy(testcv);
70 sem_destroy(donesem);
71 }
72 #endif
73
74 static
75 void
76 inititems(void)
77 {
78 if (testsem==NULL) {
79 testsem = sem_create("testsem", 2);
80 if (testsem == NULL) {
81 panic("synchtest: sem_create failed\n");
82 }
83 }
84 if (testlock==NULL) {
85 testlock = lock_create("testlock");
86 if (testlock == NULL) {
87 panic("synchtest: lock_create failed\n");
88 }
89 }
90 if (testcv==NULL) {
91 #ifdef UW
92 testcv = cv_create("testcv");
93 #else
94 testcv = cv_create("testlock");
95 #endif
96 if (testcv == NULL) {
97 panic("synchtest: cv_create failed\n");
98 }
99 }
100 if (donesem==NULL) {
101 donesem = sem_create("donesem", 0);
102 if (donesem == NULL) {
103 panic("synchtest: sem_create failed\n");
104 }
105 }
106 }
107
108 static
109 void
110 semtestthread(void *junk, unsigned long num)
111 {
112 int i;
113 (void)junk;
114
115 /*
116 * Only one of these should print at a time.
117 */
118 P(testsem);
119 kprintf("Thread %2lu: ", num);
120 for (i=0; i<NSEMLOOPS; i++) {
121 kprintf("%c", (int)num+64);
122 }
123 kprintf("\n");
124 V(donesem);
125 #ifdef UW
126 thread_exit();
127 #endif
128 }
129
130 int
131 semtest(int nargs, char **args)
132 {
133 int i, result;
134
135 (void)nargs;
136 (void)args;
137
138 inititems();
139 kprintf("Starting semaphore test...\n");
140 kprintf("If this hangs, it's broken: ");
141 P(testsem);
142 P(testsem);
143 kprintf("ok\n");
144
145 for (i=0; i<NTHREADS; i++) {
146 result = thread_fork("semtest", NULL, semtestthread, NULL, i);
147 if (result) {
148 panic("semtest: thread_fork failed: %s\n",
149 strerror(result));
150 }
151 }
152
153 for (i=0; i<NTHREADS; i++) {
154 V(testsem);
155 P(donesem);
156 }
157
158 /* so we can run it again */
159 V(testsem);
160 V(testsem);
161
162 #ifdef UW
163 cleanitems();
164 #endif
165 kprintf("Semaphore test done.\n");
166 return 0;
167 }
168
169 static
170 void
171 fail(unsigned long num, const char *msg)
172 {
173 kprintf("thread %lu: Mismatch on %s\n", num, msg);
174 kprintf("Test failed\n");
175
176 lock_release(testlock);
177
178 V(donesem);
179 thread_exit();
180 }
181
182 static
183 void
184 locktestthread(void *junk, unsigned long num)
185 {
186 int i;
187 (void)junk;
188
189 for (i=0; i<NLOCKLOOPS; i++) {
190 lock_acquire(testlock);
191 testval1 = num;
192 testval2 = num*num;
193 testval3 = num%3;
194
195 if (testval2 != testval1*testval1) {
196 fail(num, "testval2/testval1");
197 }
198
199 if (testval2%3 != (testval3*testval3)%3) {
200 fail(num, "testval2/testval3");
201 }
202
203 if (testval3 != testval1%3) {
204 fail(num, "testval3/testval1");
205 }
206
207 if (testval1 != num) {
208 fail(num, "testval1/num");
209 }
210
211 if (testval2 != num*num) {
212 fail(num, "testval2/num");
213 }
214
215 if (testval3 != num%3) {
216 fail(num, "testval3/num");
217 }
218
219 lock_release(testlock);
220 }
221 V(donesem);
222 #ifdef UW
223 thread_exit();
224 #endif
225 }
226
227
228 int
229 locktest(int nargs, char **args)
230 {
231 int i, result;
232
233 (void)nargs;
234 (void)args;
235
236 inititems();
237 kprintf("Starting lock test...\n");
238
239 for (i=0; i<NTHREADS; i++) {
240 result = thread_fork("synchtest", NULL, locktestthread,
241 NULL, i);
242 if (result) {
243 panic("locktest: thread_fork failed: %s\n",
244 strerror(result));
245 }
246 }
247 for (i=0; i<NTHREADS; i++) {
248 P(donesem);
249 }
250
251 #ifdef UW
252 cleanitems();
253 #endif
254 kprintf("Lock test done.\n");
255
256 return 0;
257 }
258
259 static
260 void
261 cvtestthread(void *junk, unsigned long num)
262 {
263 int i;
264 volatile int j;
265 time_t secs1, secs2;
266 uint32_t nsecs1, nsecs2;
267
268 (void)junk;
269
270 for (i=0; i<NCVLOOPS; i++) {
271 lock_acquire(testlock);
272 while (testval1 != num) {
273 gettime(&secs1, &nsecs1);
274 cv_wait(testcv, testlock);
275 gettime(&secs2, &nsecs2);
276
277 if (nsecs2 < nsecs1) {
278 secs2--;
279 nsecs2 += 1000000000;
280 }
281
282 nsecs2 -= nsecs1;
283 secs2 -= secs1;
284
285 /* Require at least 2000 cpu cycles (we're 25mhz) */
286 if (secs2==0 && nsecs2 < 40*2000) {
287 kprintf("cv_wait took only %u ns\n", nsecs2);
288 kprintf("That's too fast... you must be "
289 "busy-looping\n");
290 V(donesem);
291 thread_exit();
292 }
293
294 }
295 kprintf("Thread %lu\n", num);
296 testval1 = (testval1 + NTHREADS - 1)%NTHREADS;
297
298 /*
299 * loop a little while to make sure we can measure the
300 * time waiting on the cv.
301 */
302 for (j=0; j<3000; j++);
303
304 cv_broadcast(testcv, testlock);
305 lock_release(testlock);
306 }
307 V(donesem);
308 #ifdef UW
309 thread_exit();
310 #endif
311 }
312
313 int
314 cvtest(int nargs, char **args)
315 {
316
317 int i, result;
318
319 (void)nargs;
320 (void)args;
321
322 inititems();
323 kprintf("Starting CV test...\n");
324 #ifdef UW
325 kprintf("%d threads should print out in reverse order %d times.\n", NTHREADS, NCVLOOPS);
326 #else
327 kprintf("Threads should print out in reverse order.\n");
328 #endif
329
330 testval1 = NTHREADS-1;
331
332 for (i=0; i<NTHREADS; i++) {
333 result = thread_fork("synchtest", NULL, cvtestthread, NULL, i);
334 if (result) {
335 panic("cvtest: thread_fork failed: %s\n",
336 strerror(result));
337 }
338 }
339 for (i=0; i<NTHREADS; i++) {
340 P(donesem);
341 }
342
343 #ifdef UW
344 cleanitems();
345 #endif
346 kprintf("CV test done\n");
347
348 return 0;
349 }