os161-1.99
 All Data Structures
synchtest.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Synchronization test code.
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          * Only one of these should print at a time.
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         /* so we can run it again */
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                         /* Require at least 2000 cpu cycles (we're 25mhz) */
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                  * loop a little while to make sure we can measure the
00300                  * time waiting on the cv.
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 }
 All Data Structures