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 }