Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/test/synchtest.c
2091 views
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
static struct semaphore *testsem;
50
static struct lock *testlock;
51
static struct cv *testcv;
52
static struct semaphore *donesem;
53
54
static
55
void
56
inititems(void)
57
{
58
if (testsem==NULL) {
59
testsem = sem_create("testsem", 2);
60
if (testsem == NULL) {
61
panic("synchtest: sem_create failed\n");
62
}
63
}
64
if (testlock==NULL) {
65
testlock = lock_create("testlock");
66
if (testlock == NULL) {
67
panic("synchtest: lock_create failed\n");
68
}
69
}
70
if (testcv==NULL) {
71
testcv = cv_create("testlock");
72
if (testcv == NULL) {
73
panic("synchtest: cv_create failed\n");
74
}
75
}
76
if (donesem==NULL) {
77
donesem = sem_create("donesem", 0);
78
if (donesem == NULL) {
79
panic("synchtest: sem_create failed\n");
80
}
81
}
82
}
83
84
static
85
void
86
semtestthread(void *junk, unsigned long num)
87
{
88
int i;
89
(void)junk;
90
91
/*
92
* Only one of these should print at a time.
93
*/
94
P(testsem);
95
kprintf("Thread %2lu: ", num);
96
for (i=0; i<NSEMLOOPS; i++) {
97
kprintf("%c", (int)num+64);
98
}
99
kprintf("\n");
100
V(donesem);
101
}
102
103
int
104
semtest(int nargs, char **args)
105
{
106
int i, result;
107
108
(void)nargs;
109
(void)args;
110
111
inititems();
112
kprintf("Starting semaphore test...\n");
113
kprintf("If this hangs, it's broken: ");
114
P(testsem);
115
P(testsem);
116
kprintf("ok\n");
117
118
for (i=0; i<NTHREADS; i++) {
119
result = thread_fork("semtest", semtestthread, NULL, i, NULL);
120
if (result) {
121
panic("semtest: thread_fork failed: %s\n",
122
strerror(result));
123
}
124
}
125
126
for (i=0; i<NTHREADS; i++) {
127
V(testsem);
128
P(donesem);
129
}
130
131
/* so we can run it again */
132
V(testsem);
133
V(testsem);
134
135
kprintf("Semaphore test done.\n");
136
return 0;
137
}
138
139
static
140
void
141
fail(unsigned long num, const char *msg)
142
{
143
kprintf("thread %lu: Mismatch on %s\n", num, msg);
144
kprintf("Test failed\n");
145
146
lock_release(testlock);
147
148
V(donesem);
149
thread_exit();
150
}
151
152
static
153
void
154
locktestthread(void *junk, unsigned long num)
155
{
156
int i;
157
(void)junk;
158
159
for (i=0; i<NLOCKLOOPS; i++) {
160
lock_acquire(testlock);
161
testval1 = num;
162
testval2 = num*num;
163
testval3 = num%3;
164
165
if (testval2 != testval1*testval1) {
166
fail(num, "testval2/testval1");
167
}
168
169
if (testval2%3 != (testval3*testval3)%3) {
170
fail(num, "testval2/testval3");
171
}
172
173
if (testval3 != testval1%3) {
174
fail(num, "testval3/testval1");
175
}
176
177
if (testval1 != num) {
178
fail(num, "testval1/num");
179
}
180
181
if (testval2 != num*num) {
182
fail(num, "testval2/num");
183
}
184
185
if (testval3 != num%3) {
186
fail(num, "testval3/num");
187
}
188
189
lock_release(testlock);
190
}
191
V(donesem);
192
}
193
194
195
int
196
locktest(int nargs, char **args)
197
{
198
int i, result;
199
200
(void)nargs;
201
(void)args;
202
203
inititems();
204
kprintf("Starting lock test...\n");
205
206
for (i=0; i<NTHREADS; i++) {
207
result = thread_fork("synchtest", locktestthread, NULL, i,
208
NULL);
209
if (result) {
210
panic("locktest: thread_fork failed: %s\n",
211
strerror(result));
212
}
213
}
214
for (i=0; i<NTHREADS; i++) {
215
P(donesem);
216
}
217
218
kprintf("Lock test done.\n");
219
220
return 0;
221
}
222
223
static
224
void
225
cvtestthread(void *junk, unsigned long num)
226
{
227
int i;
228
volatile int j;
229
time_t secs1, secs2;
230
uint32_t nsecs1, nsecs2;
231
232
(void)junk;
233
234
for (i=0; i<NCVLOOPS; i++) {
235
lock_acquire(testlock);
236
while (testval1 != num) {
237
gettime(&secs1, &nsecs1);
238
cv_wait(testcv, testlock);
239
gettime(&secs2, &nsecs2);
240
241
if (nsecs2 < nsecs1) {
242
secs2--;
243
nsecs2 += 1000000000;
244
}
245
246
nsecs2 -= nsecs1;
247
secs2 -= secs1;
248
249
/* Require at least 2000 cpu cycles (we're 25mhz) */
250
if (secs2==0 && nsecs2 < 40*2000) {
251
kprintf("cv_wait took only %u ns\n", nsecs2);
252
kprintf("That's too fast... you must be "
253
"busy-looping\n");
254
V(donesem);
255
thread_exit();
256
}
257
258
}
259
kprintf("Thread %lu\n", num);
260
testval1 = (testval1 + NTHREADS - 1)%NTHREADS;
261
262
/*
263
* loop a little while to make sure we can measure the
264
* time waiting on the cv.
265
*/
266
for (j=0; j<3000; j++);
267
268
cv_broadcast(testcv, testlock);
269
lock_release(testlock);
270
}
271
V(donesem);
272
}
273
274
int
275
cvtest(int nargs, char **args)
276
{
277
278
int i, result;
279
280
(void)nargs;
281
(void)args;
282
283
inititems();
284
kprintf("Starting CV test...\n");
285
kprintf("Threads should print out in reverse order.\n");
286
287
testval1 = NTHREADS-1;
288
289
for (i=0; i<NTHREADS; i++) {
290
result = thread_fork("synchtest", cvtestthread, NULL, i,
291
NULL);
292
if (result) {
293
panic("cvtest: thread_fork failed: %s\n",
294
strerror(result));
295
}
296
}
297
for (i=0; i<NTHREADS; i++) {
298
P(donesem);
299
}
300
301
kprintf("CV test done\n");
302
303
return 0;
304
}
305
306
static
307
void
308
cvtest2thread(void *junk, unsigned long num)
309
{
310
int i;
311
(void)junk;
312
313
for (i=0; i<NCVLOOPS; i++) {
314
lock_acquire(testlock);
315
while (testval1 != num) {
316
testval2 = 0;
317
cv_wait(testcv, testlock);
318
testval2 = 0xFFFFFFFF;
319
}
320
testval2 = num;
321
cv_broadcast(testcv, testlock);
322
thread_yield();
323
kprintf("Thread %lu\n", testval2);
324
testval1 = (testval1 + NTHREADS - 1)%NTHREADS;
325
lock_release(testlock);
326
}
327
V(donesem);
328
}
329
330
int
331
cvtest2(int nargs, char **args)
332
{
333
int i, result;
334
335
(void)nargs;
336
(void)args;
337
338
inititems();
339
kprintf("Starting new CV test...\n");
340
kprintf("Threads should print out in reverse order.\n");
341
342
testval1 = NTHREADS-1;
343
344
for (i=0; i<NTHREADS; i++) {
345
result = thread_fork("synchtest", cvtest2thread, NULL, i,
346
NULL);
347
if (result) {
348
panic("cvtest: thread_fork failed: %s\n",
349
strerror(result));
350
}
351
}
352
for (i=0; i<NTHREADS; i++) {
353
P(donesem);
354
}
355
356
kprintf("CV test done\n");
357
358
return 0;
359
}
360
361