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 #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 
00043 
00044 #if OPT_SYNCHPROBS
00045 #define DIM 10
00046 #else
00047 #define DIM 70
00048 #endif
00049 
00050 
00051 #define SLEEPALOT_PRINTS      20        
00052 #define SLEEPALOT_ITERS       4         
00053 
00054 #define WAKER_WAKES          100
00055 
00056 #define COMPUTE_ITERS         10
00057 
00058 #define NWAITCHANS 12
00059 static struct wchan *waitchans[NWAITCHANS];  
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 }