/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- setup
- sleepalot_thread
- waker_thread
- make_sleepalots
- compute_thread
- make_computes
- finish
- runtest3
- threadtest3
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 * More thread test code.
32 */
33 #include <types.h>
34 #include <lib.h>
35 #include <wchan.h>
36 #include <thread.h>
37 #include <synch.h>
38 #include <test.h>
39
40 #include "opt-synchprobs.h"
41
42 /* dimension of matrices (cannot be too large or will overflow stack) */
43
44 #if OPT_SYNCHPROBS
45 #define DIM 10
46 #else
47 #define DIM 70
48 #endif
49
50 /* number of iterations for sleepalot threads */
51 #define SLEEPALOT_PRINTS 20 /* number of printouts */
52 #define SLEEPALOT_ITERS 4 /* iterations per printout */
53 /* polling frequency of waker thread */
54 #define WAKER_WAKES 100
55 /* number of iterations per compute thread */
56 #define COMPUTE_ITERS 10
57
58 #define NWAITCHANS 12
59 static struct wchan *waitchans[NWAITCHANS]; /* N distinct wait channels */
60
61 static volatile int wakerdone;
62 static struct semaphore *wakersem;
63 static struct semaphore *donesem;
64
65 static
66 void
67 setup(void)
68 {
69 char tmp[16];
70 int i;
71
72 if (wakersem == NULL) {
73 wakersem = sem_create("wakersem", 1);
74 donesem = sem_create("donesem", 0);
75 for (i=0; i<NWAITCHANS; i++) {
76 snprintf(tmp, sizeof(tmp), "wc%d", i);
77 waitchans[i] = wchan_create(kstrdup(tmp));
78 }
79 }
80 wakerdone = 0;
81 }
82
83 static
84 void
85 sleepalot_thread(void *junk, unsigned long num)
86 {
87 int i, j;
88
89 (void)junk;
90
91 for (i=0; i<SLEEPALOT_PRINTS; i++) {
92 for (j=0; j<SLEEPALOT_ITERS; j++) {
93 struct wchan *w;
94
95 w = waitchans[random()%NWAITCHANS];
96 wchan_lock(w);
97 wchan_sleep(w);
98 }
99 kprintf("[%lu]", num);
100 }
101 V(donesem);
102 }
103
104 static
105 void
106 waker_thread(void *junk1, unsigned long junk2)
107 {
108 int i, done;
109
110 (void)junk1;
111 (void)junk2;
112
113 while (1) {
114 P(wakersem);
115 done = wakerdone;
116 V(wakersem);
117 if (done) {
118 break;
119 }
120
121 for (i=0; i<WAKER_WAKES; i++) {
122 struct wchan *w;
123
124 w = waitchans[random()%NWAITCHANS];
125 wchan_wakeall(w);
126
127 thread_yield();
128 }
129 }
130 V(donesem);
131 }
132
133 static
134 void
135 make_sleepalots(int howmany)
136 {
137 char name[16];
138 int i, result;
139
140 for (i=0; i<howmany; i++) {
141 snprintf(name, sizeof(name), "sleepalot%d", i);
142 result = thread_fork(name, NULL, sleepalot_thread, NULL, i);
143 if (result) {
144 panic("thread_fork failed: %s\n", strerror(result));
145 }
146 }
147 result = thread_fork("waker", NULL, waker_thread, NULL, 0);
148 if (result) {
149 panic("thread_fork failed: %s\n", strerror(result));
150 }
151 }
152
153 static
154 void
155 compute_thread(void *junk1, unsigned long num)
156 {
157 struct matrix {
158 char m[DIM][DIM];
159 };
160 struct matrix *m1, *m2, *m3;
161 unsigned char tot;
162 int i, j, k, m;
163 uint32_t rand;
164
165 (void)junk1;
166
167 m1 = kmalloc(sizeof(struct matrix));
168 KASSERT(m1 != NULL);
169 m2 = kmalloc(sizeof(struct matrix));
170 KASSERT(m2 != NULL);
171 m3 = kmalloc(sizeof(struct matrix));
172 KASSERT(m3 != NULL);
173
174 for (m=0; m<COMPUTE_ITERS; m++) {
175
176 for (i=0; i<DIM; i++) {
177 for (j=0; j<DIM; j++) {
178 rand = random();
179 m1->m[i][j] = rand >> 16;
180 m2->m[i][j] = rand & 0xffff;
181 }
182 }
183
184 for (i=0; i<DIM; i++) {
185 for (j=0; j<DIM; j++) {
186 tot = 0;
187 for (k=0; k<DIM; k++) {
188 tot += m1->m[i][k] * m2->m[k][j];
189 }
190 m3->m[i][j] = tot;
191 }
192 }
193
194 tot = 0;
195 for (i=0; i<DIM; i++) {
196 tot += m3->m[i][i];
197 }
198
199 kprintf("{%lu: %u}", num, (unsigned) tot);
200 thread_yield();
201 }
202
203 kfree(m1);
204 kfree(m2);
205 kfree(m3);
206
207 V(donesem);
208 }
209
210 static
211 void
212 make_computes(int howmany)
213 {
214 char name[16];
215 int i, result;
216
217 for (i=0; i<howmany; i++) {
218 snprintf(name, sizeof(name), "compute%d", i);
219 result = thread_fork(name, NULL, compute_thread, NULL, i);
220 if (result) {
221 panic("thread_fork failed: %s\n", strerror(result));
222 }
223 }
224 }
225
226 static
227 void
228 finish(int howmanytotal)
229 {
230 int i;
231 for (i=0; i<howmanytotal; i++) {
232 P(donesem);
233 }
234 P(wakersem);
235 wakerdone = 1;
236 V(wakersem);
237 P(donesem);
238 }
239
240 static
241 void
242 runtest3(int nsleeps, int ncomputes)
243 {
244 setup();
245 kprintf("Starting thread test 3 (%d [sleepalots], %d {computes}, "
246 "1 waker)\n",
247 nsleeps, ncomputes);
248 make_sleepalots(nsleeps);
249 make_computes(ncomputes);
250 finish(nsleeps+ncomputes);
251 kprintf("\nThread test 3 done\n");
252 }
253
254 int
255 threadtest3(int nargs, char **args)
256 {
257 if (nargs==1) {
258 runtest3(5, 2);
259 }
260 else if (nargs==3) {
261 runtest3(atoi(args[1]), atoi(args[2]));
262 }
263 else {
264 kprintf("Usage: tt3 [sleepthreads computethreads]\n");
265 return 1;
266 }
267 return 0;
268 }