os161-1.99
 All Data Structures
parallelvm.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  * parallelvm.c: highly parallelized VM stress test.
00032  *
00033  * This test probably won't run with only 512k of physical memory
00034  * (unless maybe if you have a *really* gonzo VM system) because each
00035  * of its processes needs to allocate a kernel stack, and those add up
00036  * quickly.
00037  */
00038 
00039 #include <sys/types.h>
00040 #include <sys/wait.h>
00041 #include <stdarg.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <unistd.h>
00046 #include <err.h>
00047 
00048 #define NJOBS    24
00049 
00050 #define DIM      35
00051 #define NMATS    11
00052 #define JOBSIZE  ((NMATS+1)*DIM*DIM*sizeof(int))
00053 
00054 static const int right_answers[NJOBS] = {
00055         -1337312809,
00056         356204544,
00057         -537881911,
00058         -65406976,
00059         1952063315,
00060         -843894784,
00061         1597000869,
00062         -993925120,
00063         838840559,
00064         -1616928768,
00065         -182386335,
00066         -364554240,
00067         251084843,
00068         -61403136,
00069         295326333,
00070         1488013312,
00071         1901440647,
00072         0,
00073         -1901440647,
00074         -1488013312,
00075         -295326333,
00076         61403136,
00077         -251084843,
00078         364554240,
00079 };
00080 
00081 ////////////////////////////////////////////////////////////
00082 
00083 struct matrix {
00084         int m_data[DIM][DIM];
00085 };
00086 
00087 ////////////////////////////////////////////////////////////
00088 
00089 /*
00090  * Use this instead of just calling printf so we know each printout
00091  * is atomic; this prevents the lines from getting intermingled.
00092  */
00093 static
00094 void
00095 say(const char *fmt, ...)
00096 {
00097         char buf[256];
00098         va_list ap;
00099         va_start(ap, fmt);
00100         vsnprintf(buf, sizeof(buf), fmt, ap);
00101         va_end(ap);
00102         write(STDOUT_FILENO, buf, strlen(buf));
00103 }
00104 
00105 ////////////////////////////////////////////////////////////
00106 
00107 static
00108 void
00109 multiply(struct matrix *res, const struct matrix *m1, const struct matrix *m2)
00110 {
00111         int i, j, k;
00112 
00113         for (i=0; i<DIM; i++) {
00114                 for (j=0; j<DIM; j++) {
00115                         int val=0;
00116                         for (k=0; k<DIM; k++) {
00117                                 val += m1->m_data[i][k]*m2->m_data[k][j];
00118                         }
00119                         res->m_data[i][j] = val;
00120                 }
00121         }
00122 }
00123 
00124 static
00125 void
00126 addeq(struct matrix *m1, const struct matrix *m2)
00127 {
00128         int i, j;
00129         for (i=0; i<DIM; i++) {
00130                 for (j=0; j<DIM; j++) {
00131                         m1->m_data[i][j] += m2->m_data[i][j];
00132                 }
00133         }
00134 }
00135 
00136 static
00137 int
00138 trace(const struct matrix *m1)
00139 {
00140         int i, t=0;
00141         for (i=0; i<DIM; i++) {
00142                 t += m1->m_data[i][i];
00143         }
00144         return t;
00145 }
00146 
00147 ////////////////////////////////////////////////////////////
00148 
00149 static struct matrix mats[NMATS];
00150 
00151 static
00152 void
00153 populate_initial_matrixes(int mynum)
00154 {
00155         int i,j;
00156         struct matrix *m = &mats[0];
00157         for (i=0; i<DIM; i++) {
00158                 for (j=0; j<DIM; j++) {
00159                         m->m_data[i][j] = mynum+i-2*j;
00160                 }
00161         }
00162         
00163         multiply(&mats[1], &mats[0], &mats[0]);
00164 }
00165 
00166 static
00167 void
00168 compute(int n)
00169 {
00170         struct matrix tmp;
00171         int i, j;
00172 
00173         for (i=0,j=n-1; i<j; i++,j--) {
00174                 multiply(&tmp, &mats[i], &mats[j]);
00175                 addeq(&mats[n], &tmp);
00176         }
00177 }
00178 
00179 static
00180 void
00181 computeall(int mynum)
00182 {
00183         int i;
00184         populate_initial_matrixes(mynum);
00185         for (i=2; i<NMATS; i++) {
00186                 compute(i);
00187         }
00188 }
00189 
00190 static
00191 int
00192 answer(void)
00193 {
00194         return trace(&mats[NMATS-1]);
00195 }
00196 
00197 static
00198 void
00199 go(int mynum)
00200 {
00201         int r;
00202 
00203         say("Process %d (pid %d) starting computation...\n", mynum, 
00204             (int) getpid());
00205 
00206         computeall(mynum);
00207         r = answer();
00208 
00209         if (r != right_answers[mynum]) {
00210                 say("Process %d answer %d: FAILED, should be %d\n", 
00211                     mynum, r, right_answers[mynum]);
00212                 exit(1);
00213         }
00214         say("Process %d answer %d: passed\n", mynum, r);
00215         exit(0);
00216 }
00217 
00218 ////////////////////////////////////////////////////////////
00219 
00220 static
00221 int
00222 status_is_failure(int status)
00223 {
00224         /* Proper interpretation of Unix exit status */
00225         if (WIFSIGNALED(status)) {
00226                 return 1;
00227         }
00228         if (!WIFEXITED(status)) {
00229                 /* ? */
00230                 return 1;
00231         }
00232         status = WEXITSTATUS(status);
00233         return status != 0;
00234 }
00235 
00236 static
00237 void
00238 makeprocs(void)
00239 {
00240         int i, status, failcount;
00241         pid_t pids[NJOBS];
00242 
00243         printf("Job size approximately %lu bytes\n", (unsigned long) JOBSIZE);
00244         printf("Forking %d jobs; total load %luk\n", NJOBS,
00245                (unsigned long) (NJOBS * JOBSIZE)/1024);
00246 
00247         for (i=0; i<NJOBS; i++) {
00248                 pids[i] = fork();
00249                 if (pids[i]<0) {
00250                         warn("fork");
00251                 }
00252                 if (pids[i]==0) {
00253                         /* child */
00254                         go(i);
00255                 }
00256         }
00257 
00258         failcount=0;
00259         for (i=0; i<NJOBS; i++) {
00260                 if (pids[i]<0) {
00261                         failcount++;
00262                 }
00263                 else {
00264                         if (waitpid(pids[i], &status, 0)<0) {
00265                                 err(1, "waitpid");
00266                         }
00267                         if (status_is_failure(status)) {
00268                                 failcount++;
00269                         }
00270                 }
00271         }
00272 
00273         if (failcount>0) {
00274                 printf("%d subprocesses failed\n", failcount);
00275                 exit(1);
00276         }
00277         printf("Test complete\n");
00278 }
00279 
00280 int
00281 main()
00282 {
00283         makeprocs();
00284         return 0;
00285 }
 All Data Structures