os161-1.99
 All Data Structures
tt3.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  * More thread test code.
00032  */
00033 #include <types.h>
00034 #include <lib.h>
00035 #include <wchan.h>
00036 #include <thread.h>
00037 #include <synch.h>
00038 #include <test.h>
00039 
00040 #include "opt-synchprobs.h"
00041 
00042 /* dimension of matrices (cannot be too large or will overflow stack) */
00043 
00044 #if OPT_SYNCHPROBS
00045 #define DIM 10
00046 #else
00047 #define DIM 70
00048 #endif
00049 
00050 /* number of iterations for sleepalot threads */
00051 #define SLEEPALOT_PRINTS      20        /* number of printouts */
00052 #define SLEEPALOT_ITERS       4         /* iterations per printout */
00053 /* polling frequency of waker thread */
00054 #define WAKER_WAKES          100
00055 /* number of iterations per compute thread */
00056 #define COMPUTE_ITERS         10
00057 
00058 #define NWAITCHANS 12
00059 static struct wchan *waitchans[NWAITCHANS];  /* N distinct wait channels */
00060 
00061 static volatile int wakerdone;
00062 static struct semaphore *wakersem;
00063 static struct semaphore *donesem;
00064 
00065 static
00066 void
00067 setup(void)
00068 {
00069         char tmp[16];
00070         int i;
00071 
00072         if (wakersem == NULL) {
00073                 wakersem = sem_create("wakersem", 1);
00074                 donesem = sem_create("donesem", 0);
00075                 for (i=0; i<NWAITCHANS; i++) {
00076                         snprintf(tmp, sizeof(tmp), "wc%d", i);
00077                         waitchans[i] = wchan_create(kstrdup(tmp));
00078                 }
00079         }
00080         wakerdone = 0;
00081 }
00082 
00083 static
00084 void
00085 sleepalot_thread(void *junk, unsigned long num)
00086 {
00087         int i, j;
00088 
00089         (void)junk;
00090 
00091         for (i=0; i<SLEEPALOT_PRINTS; i++) {
00092                 for (j=0; j<SLEEPALOT_ITERS; j++) {
00093                         struct wchan *w;
00094 
00095                         w = waitchans[random()%NWAITCHANS];
00096                         wchan_lock(w);
00097                         wchan_sleep(w);
00098                 }
00099                 kprintf("[%lu]", num);
00100         }
00101         V(donesem);
00102 }
00103 
00104 static
00105 void
00106 waker_thread(void *junk1, unsigned long junk2)
00107 {
00108         int i, done;
00109 
00110         (void)junk1;
00111         (void)junk2;
00112 
00113         while (1) {
00114                 P(wakersem);
00115                 done = wakerdone;
00116                 V(wakersem);
00117                 if (done) {
00118                         break;
00119                 }
00120 
00121                 for (i=0; i<WAKER_WAKES; i++) {
00122                         struct wchan *w;
00123 
00124                         w = waitchans[random()%NWAITCHANS];
00125                         wchan_wakeall(w);
00126 
00127                         thread_yield();
00128                 }
00129         }
00130         V(donesem);
00131 }
00132 
00133 static
00134 void
00135 make_sleepalots(int howmany)
00136 {
00137         char name[16];
00138         int i, result;
00139 
00140         for (i=0; i<howmany; i++) {
00141                 snprintf(name, sizeof(name), "sleepalot%d", i);
00142                 result = thread_fork(name, NULL, sleepalot_thread, NULL, i);
00143                 if (result) {
00144                         panic("thread_fork failed: %s\n", strerror(result));
00145                 }
00146         }
00147         result = thread_fork("waker", NULL, waker_thread, NULL, 0);
00148         if (result) {
00149                 panic("thread_fork failed: %s\n", strerror(result));
00150         }
00151 }
00152 
00153 static
00154 void
00155 compute_thread(void *junk1, unsigned long num)
00156 {
00157         struct matrix {
00158                 char m[DIM][DIM];
00159         };
00160         struct matrix *m1, *m2, *m3;
00161         unsigned char tot;
00162         int i, j, k, m;
00163         uint32_t rand;
00164 
00165         (void)junk1;
00166 
00167         m1 = kmalloc(sizeof(struct matrix));
00168         KASSERT(m1 != NULL);
00169         m2 = kmalloc(sizeof(struct matrix));
00170         KASSERT(m2 != NULL);
00171         m3 = kmalloc(sizeof(struct matrix));
00172         KASSERT(m3 != NULL);
00173 
00174         for (m=0; m<COMPUTE_ITERS; m++) {
00175 
00176                 for (i=0; i<DIM; i++) {
00177                         for (j=0; j<DIM; j++) {
00178                                 rand = random();
00179                                 m1->m[i][j] = rand >> 16;
00180                                 m2->m[i][j] = rand & 0xffff;
00181                         }
00182                 }
00183                 
00184                 for (i=0; i<DIM; i++) {
00185                         for (j=0; j<DIM; j++) {
00186                                 tot = 0;
00187                                 for (k=0; k<DIM; k++) {
00188                                         tot += m1->m[i][k] * m2->m[k][j];
00189                                 }
00190                                 m3->m[i][j] = tot;
00191                         }
00192                 }
00193                 
00194                 tot = 0;
00195                 for (i=0; i<DIM; i++) {
00196                         tot += m3->m[i][i];
00197                 }
00198 
00199                 kprintf("{%lu: %u}", num, (unsigned) tot);
00200                 thread_yield();
00201         }
00202 
00203         kfree(m1);
00204         kfree(m2);
00205         kfree(m3);
00206 
00207         V(donesem);
00208 }
00209 
00210 static
00211 void
00212 make_computes(int howmany)
00213 {
00214         char name[16];
00215         int i, result;
00216 
00217         for (i=0; i<howmany; i++) {
00218                 snprintf(name, sizeof(name), "compute%d", i);
00219                 result = thread_fork(name, NULL, compute_thread, NULL, i);
00220                 if (result) {
00221                         panic("thread_fork failed: %s\n", strerror(result));
00222                 }
00223         }
00224 }
00225 
00226 static
00227 void
00228 finish(int howmanytotal)
00229 {
00230         int i;
00231         for (i=0; i<howmanytotal; i++) {
00232                 P(donesem);
00233         }
00234         P(wakersem);
00235         wakerdone = 1;
00236         V(wakersem);
00237         P(donesem);
00238 }
00239 
00240 static
00241 void
00242 runtest3(int nsleeps, int ncomputes)
00243 {
00244         setup();
00245         kprintf("Starting thread test 3 (%d [sleepalots], %d {computes}, "
00246                 "1 waker)\n",
00247                 nsleeps, ncomputes);
00248         make_sleepalots(nsleeps);
00249         make_computes(ncomputes);
00250         finish(nsleeps+ncomputes);
00251         kprintf("\nThread test 3 done\n");
00252 }
00253 
00254 int
00255 threadtest3(int nargs, char **args)
00256 {
00257         if (nargs==1) {
00258                 runtest3(5, 2);
00259         }
00260         else if (nargs==3) {
00261                 runtest3(atoi(args[1]), atoi(args[2]));
00262         }
00263         else {
00264                 kprintf("Usage: tt3 [sleepthreads computethreads]\n");
00265                 return 1;
00266         }
00267         return 0;
00268 }
 All Data Structures