00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <types.h>
00035 #include <lib.h>
00036 #include <clock.h>
00037 #include <thread.h>
00038 #include <synch.h>
00039 #include <test.h>
00040
00041 #define NSEMLOOPS 63
00042 #define NLOCKLOOPS 120
00043 #define NCVLOOPS 5
00044 #define NTHREADS 32
00045
00046 static volatile unsigned long testval1;
00047 static volatile unsigned long testval2;
00048 static volatile unsigned long testval3;
00049 #ifdef UW
00050 static struct semaphore *testsem = 0;
00051 static struct lock *testlock = 0;
00052 static struct cv *testcv = 0;
00053 static struct semaphore *donesem = 0;
00054 #else
00055 static struct semaphore *testsem;
00056 static struct lock *testlock;
00057 static struct cv *testcv;
00058 static struct semaphore *donesem;
00059 #endif
00060
00061 #ifdef UW
00062 static
00063 void
00064 cleanitems(void)
00065 {
00066 kprintf("cleanitems: Destroying sems, locks, and cvs\n");
00067 sem_destroy(testsem);
00068 lock_destroy(testlock);
00069 cv_destroy(testcv);
00070 sem_destroy(donesem);
00071 }
00072 #endif
00073
00074 static
00075 void
00076 inititems(void)
00077 {
00078 if (testsem==NULL) {
00079 testsem = sem_create("testsem", 2);
00080 if (testsem == NULL) {
00081 panic("synchtest: sem_create failed\n");
00082 }
00083 }
00084 if (testlock==NULL) {
00085 testlock = lock_create("testlock");
00086 if (testlock == NULL) {
00087 panic("synchtest: lock_create failed\n");
00088 }
00089 }
00090 if (testcv==NULL) {
00091 #ifdef UW
00092 testcv = cv_create("testcv");
00093 #else
00094 testcv = cv_create("testlock");
00095 #endif
00096 if (testcv == NULL) {
00097 panic("synchtest: cv_create failed\n");
00098 }
00099 }
00100 if (donesem==NULL) {
00101 donesem = sem_create("donesem", 0);
00102 if (donesem == NULL) {
00103 panic("synchtest: sem_create failed\n");
00104 }
00105 }
00106 }
00107
00108 static
00109 void
00110 semtestthread(void *junk, unsigned long num)
00111 {
00112 int i;
00113 (void)junk;
00114
00115
00116
00117
00118 P(testsem);
00119 kprintf("Thread %2lu: ", num);
00120 for (i=0; i<NSEMLOOPS; i++) {
00121 kprintf("%c", (int)num+64);
00122 }
00123 kprintf("\n");
00124 V(donesem);
00125 #ifdef UW
00126 thread_exit();
00127 #endif
00128 }
00129
00130 int
00131 semtest(int nargs, char **args)
00132 {
00133 int i, result;
00134
00135 (void)nargs;
00136 (void)args;
00137
00138 inititems();
00139 kprintf("Starting semaphore test...\n");
00140 kprintf("If this hangs, it's broken: ");
00141 P(testsem);
00142 P(testsem);
00143 kprintf("ok\n");
00144
00145 for (i=0; i<NTHREADS; i++) {
00146 result = thread_fork("semtest", NULL, semtestthread, NULL, i);
00147 if (result) {
00148 panic("semtest: thread_fork failed: %s\n",
00149 strerror(result));
00150 }
00151 }
00152
00153 for (i=0; i<NTHREADS; i++) {
00154 V(testsem);
00155 P(donesem);
00156 }
00157
00158
00159 V(testsem);
00160 V(testsem);
00161
00162 #ifdef UW
00163 cleanitems();
00164 #endif
00165 kprintf("Semaphore test done.\n");
00166 return 0;
00167 }
00168
00169 static
00170 void
00171 fail(unsigned long num, const char *msg)
00172 {
00173 kprintf("thread %lu: Mismatch on %s\n", num, msg);
00174 kprintf("Test failed\n");
00175
00176 lock_release(testlock);
00177
00178 V(donesem);
00179 thread_exit();
00180 }
00181
00182 static
00183 void
00184 locktestthread(void *junk, unsigned long num)
00185 {
00186 int i;
00187 (void)junk;
00188
00189 for (i=0; i<NLOCKLOOPS; i++) {
00190 lock_acquire(testlock);
00191 testval1 = num;
00192 testval2 = num*num;
00193 testval3 = num%3;
00194
00195 if (testval2 != testval1*testval1) {
00196 fail(num, "testval2/testval1");
00197 }
00198
00199 if (testval2%3 != (testval3*testval3)%3) {
00200 fail(num, "testval2/testval3");
00201 }
00202
00203 if (testval3 != testval1%3) {
00204 fail(num, "testval3/testval1");
00205 }
00206
00207 if (testval1 != num) {
00208 fail(num, "testval1/num");
00209 }
00210
00211 if (testval2 != num*num) {
00212 fail(num, "testval2/num");
00213 }
00214
00215 if (testval3 != num%3) {
00216 fail(num, "testval3/num");
00217 }
00218
00219 lock_release(testlock);
00220 }
00221 V(donesem);
00222 #ifdef UW
00223 thread_exit();
00224 #endif
00225 }
00226
00227
00228 int
00229 locktest(int nargs, char **args)
00230 {
00231 int i, result;
00232
00233 (void)nargs;
00234 (void)args;
00235
00236 inititems();
00237 kprintf("Starting lock test...\n");
00238
00239 for (i=0; i<NTHREADS; i++) {
00240 result = thread_fork("synchtest", NULL, locktestthread,
00241 NULL, i);
00242 if (result) {
00243 panic("locktest: thread_fork failed: %s\n",
00244 strerror(result));
00245 }
00246 }
00247 for (i=0; i<NTHREADS; i++) {
00248 P(donesem);
00249 }
00250
00251 #ifdef UW
00252 cleanitems();
00253 #endif
00254 kprintf("Lock test done.\n");
00255
00256 return 0;
00257 }
00258
00259 static
00260 void
00261 cvtestthread(void *junk, unsigned long num)
00262 {
00263 int i;
00264 volatile int j;
00265 time_t secs1, secs2;
00266 uint32_t nsecs1, nsecs2;
00267
00268 (void)junk;
00269
00270 for (i=0; i<NCVLOOPS; i++) {
00271 lock_acquire(testlock);
00272 while (testval1 != num) {
00273 gettime(&secs1, &nsecs1);
00274 cv_wait(testcv, testlock);
00275 gettime(&secs2, &nsecs2);
00276
00277 if (nsecs2 < nsecs1) {
00278 secs2--;
00279 nsecs2 += 1000000000;
00280 }
00281
00282 nsecs2 -= nsecs1;
00283 secs2 -= secs1;
00284
00285
00286 if (secs2==0 && nsecs2 < 40*2000) {
00287 kprintf("cv_wait took only %u ns\n", nsecs2);
00288 kprintf("That's too fast... you must be "
00289 "busy-looping\n");
00290 V(donesem);
00291 thread_exit();
00292 }
00293
00294 }
00295 kprintf("Thread %lu\n", num);
00296 testval1 = (testval1 + NTHREADS - 1)%NTHREADS;
00297
00298
00299
00300
00301
00302 for (j=0; j<3000; j++);
00303
00304 cv_broadcast(testcv, testlock);
00305 lock_release(testlock);
00306 }
00307 V(donesem);
00308 #ifdef UW
00309 thread_exit();
00310 #endif
00311 }
00312
00313 int
00314 cvtest(int nargs, char **args)
00315 {
00316
00317 int i, result;
00318
00319 (void)nargs;
00320 (void)args;
00321
00322 inititems();
00323 kprintf("Starting CV test...\n");
00324 #ifdef UW
00325 kprintf("%d threads should print out in reverse order %d times.\n", NTHREADS, NCVLOOPS);
00326 #else
00327 kprintf("Threads should print out in reverse order.\n");
00328 #endif
00329
00330 testval1 = NTHREADS-1;
00331
00332 for (i=0; i<NTHREADS; i++) {
00333 result = thread_fork("synchtest", NULL, cvtestthread, NULL, i);
00334 if (result) {
00335 panic("cvtest: thread_fork failed: %s\n",
00336 strerror(result));
00337 }
00338 }
00339 for (i=0; i<NTHREADS; i++) {
00340 P(donesem);
00341 }
00342
00343 #ifdef UW
00344 cleanitems();
00345 #endif
00346 kprintf("CV test done\n");
00347
00348 return 0;
00349 }