/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- say
- multiply
- addeq
- trace
- populate_initial_matrixes
- compute
- computeall
- answer
- go
- status_is_failure
- makeprocs
- main
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 * parallelvm.c: highly parallelized VM stress test.
32 *
33 * This test probably won't run with only 512k of physical memory
34 * (unless maybe if you have a *really* gonzo VM system) because each
35 * of its processes needs to allocate a kernel stack, and those add up
36 * quickly.
37 */
38
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <err.h>
47
48 #define NJOBS 24
49
50 #define DIM 35
51 #define NMATS 11
52 #define JOBSIZE ((NMATS+1)*DIM*DIM*sizeof(int))
53
54 static const int right_answers[NJOBS] = {
55 -1337312809,
56 356204544,
57 -537881911,
58 -65406976,
59 1952063315,
60 -843894784,
61 1597000869,
62 -993925120,
63 838840559,
64 -1616928768,
65 -182386335,
66 -364554240,
67 251084843,
68 -61403136,
69 295326333,
70 1488013312,
71 1901440647,
72 0,
73 -1901440647,
74 -1488013312,
75 -295326333,
76 61403136,
77 -251084843,
78 364554240,
79 };
80
81 ////////////////////////////////////////////////////////////
82
83 struct matrix {
84 int m_data[DIM][DIM];
85 };
86
87 ////////////////////////////////////////////////////////////
88
89 /*
90 * Use this instead of just calling printf so we know each printout
91 * is atomic; this prevents the lines from getting intermingled.
92 */
93 static
94 void
95 say(const char *fmt, ...)
96 {
97 char buf[256];
98 va_list ap;
99 va_start(ap, fmt);
100 vsnprintf(buf, sizeof(buf), fmt, ap);
101 va_end(ap);
102 write(STDOUT_FILENO, buf, strlen(buf));
103 }
104
105 ////////////////////////////////////////////////////////////
106
107 static
108 void
109 multiply(struct matrix *res, const struct matrix *m1, const struct matrix *m2)
110 {
111 int i, j, k;
112
113 for (i=0; i<DIM; i++) {
114 for (j=0; j<DIM; j++) {
115 int val=0;
116 for (k=0; k<DIM; k++) {
117 val += m1->m_data[i][k]*m2->m_data[k][j];
118 }
119 res->m_data[i][j] = val;
120 }
121 }
122 }
123
124 static
125 void
126 addeq(struct matrix *m1, const struct matrix *m2)
127 {
128 int i, j;
129 for (i=0; i<DIM; i++) {
130 for (j=0; j<DIM; j++) {
131 m1->m_data[i][j] += m2->m_data[i][j];
132 }
133 }
134 }
135
136 static
137 int
138 trace(const struct matrix *m1)
139 {
140 int i, t=0;
141 for (i=0; i<DIM; i++) {
142 t += m1->m_data[i][i];
143 }
144 return t;
145 }
146
147 ////////////////////////////////////////////////////////////
148
149 static struct matrix mats[NMATS];
150
151 static
152 void
153 populate_initial_matrixes(int mynum)
154 {
155 int i,j;
156 struct matrix *m = &mats[0];
157 for (i=0; i<DIM; i++) {
158 for (j=0; j<DIM; j++) {
159 m->m_data[i][j] = mynum+i-2*j;
160 }
161 }
162
163 multiply(&mats[1], &mats[0], &mats[0]);
164 }
165
166 static
167 void
168 compute(int n)
169 {
170 struct matrix tmp;
171 int i, j;
172
173 for (i=0,j=n-1; i<j; i++,j--) {
174 multiply(&tmp, &mats[i], &mats[j]);
175 addeq(&mats[n], &tmp);
176 }
177 }
178
179 static
180 void
181 computeall(int mynum)
182 {
183 int i;
184 populate_initial_matrixes(mynum);
185 for (i=2; i<NMATS; i++) {
186 compute(i);
187 }
188 }
189
190 static
191 int
192 answer(void)
193 {
194 return trace(&mats[NMATS-1]);
195 }
196
197 static
198 void
199 go(int mynum)
200 {
201 int r;
202
203 say("Process %d (pid %d) starting computation...\n", mynum,
204 (int) getpid());
205
206 computeall(mynum);
207 r = answer();
208
209 if (r != right_answers[mynum]) {
210 say("Process %d answer %d: FAILED, should be %d\n",
211 mynum, r, right_answers[mynum]);
212 exit(1);
213 }
214 say("Process %d answer %d: passed\n", mynum, r);
215 exit(0);
216 }
217
218 ////////////////////////////////////////////////////////////
219
220 static
221 int
222 status_is_failure(int status)
223 {
224 /* Proper interpretation of Unix exit status */
225 if (WIFSIGNALED(status)) {
226 return 1;
227 }
228 if (!WIFEXITED(status)) {
229 /* ? */
230 return 1;
231 }
232 status = WEXITSTATUS(status);
233 return status != 0;
234 }
235
236 static
237 void
238 makeprocs(void)
239 {
240 int i, status, failcount;
241 pid_t pids[NJOBS];
242
243 printf("Job size approximately %lu bytes\n", (unsigned long) JOBSIZE);
244 printf("Forking %d jobs; total load %luk\n", NJOBS,
245 (unsigned long) (NJOBS * JOBSIZE)/1024);
246
247 for (i=0; i<NJOBS; i++) {
248 pids[i] = fork();
249 if (pids[i]<0) {
250 warn("fork");
251 }
252 if (pids[i]==0) {
253 /* child */
254 go(i);
255 }
256 }
257
258 failcount=0;
259 for (i=0; i<NJOBS; i++) {
260 if (pids[i]<0) {
261 failcount++;
262 }
263 else {
264 if (waitpid(pids[i], &status, 0)<0) {
265 err(1, "waitpid");
266 }
267 if (status_is_failure(status)) {
268 failcount++;
269 }
270 }
271 }
272
273 if (failcount>0) {
274 printf("%d subprocesses failed\n", failcount);
275 exit(1);
276 }
277 printf("Test complete\n");
278 }
279
280 int
281 main()
282 {
283 makeprocs();
284 return 0;
285 }