root/kern/test/synchtest.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cleanitems
  2. inititems
  3. semtestthread
  4. semtest
  5. fail
  6. locktestthread
  7. locktest
  8. cvtestthread
  9. 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 }

/* [<][>][^][v][top][bottom][index][help] */