/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* parallelvm.c: highly parallelized VM stress test.31*32* This test probably won't run with only 512k of physical memory33* (unless maybe if you have a *really* gonzo VM system) because each34* of its processes needs to allocate a kernel stack, and those add up35* quickly.36*/3738#include <sys/types.h>39#include <sys/wait.h>40#include <stdarg.h>41#include <stdio.h>42#include <string.h>43#include <stdlib.h>44#include <unistd.h>45#include <err.h>4647#define NJOBS 244849#define DIM 3550#define NMATS 1151#define JOBSIZE ((NMATS+1)*DIM*DIM*sizeof(int))5253static const int right_answers[NJOBS] = {54-1337312809,55356204544,56-537881911,57-65406976,581952063315,59-843894784,601597000869,61-993925120,62838840559,63-1616928768,64-182386335,65-364554240,66251084843,67-61403136,68295326333,691488013312,701901440647,710,72-1901440647,73-1488013312,74-295326333,7561403136,76-251084843,77364554240,78};7980////////////////////////////////////////////////////////////8182struct matrix {83int m_data[DIM][DIM];84};8586////////////////////////////////////////////////////////////8788/*89* Use this instead of just calling printf so we know each printout90* is atomic; this prevents the lines from getting intermingled.91*/92static93void94say(const char *fmt, ...)95{96char buf[256];97va_list ap;98va_start(ap, fmt);99vsnprintf(buf, sizeof(buf), fmt, ap);100va_end(ap);101write(STDOUT_FILENO, buf, strlen(buf));102}103104////////////////////////////////////////////////////////////105106static107void108multiply(struct matrix *res, const struct matrix *m1, const struct matrix *m2)109{110int i, j, k;111112for (i=0; i<DIM; i++) {113for (j=0; j<DIM; j++) {114int val=0;115for (k=0; k<DIM; k++) {116val += m1->m_data[i][k]*m2->m_data[k][j];117}118res->m_data[i][j] = val;119}120}121}122123static124void125addeq(struct matrix *m1, const struct matrix *m2)126{127int i, j;128for (i=0; i<DIM; i++) {129for (j=0; j<DIM; j++) {130m1->m_data[i][j] += m2->m_data[i][j];131}132}133}134135static136int137trace(const struct matrix *m1)138{139int i, t=0;140for (i=0; i<DIM; i++) {141t += m1->m_data[i][i];142}143return t;144}145146////////////////////////////////////////////////////////////147148static struct matrix mats[NMATS];149150static151void152populate_initial_matrixes(int mynum)153{154int i,j;155struct matrix *m = &mats[0];156for (i=0; i<DIM; i++) {157for (j=0; j<DIM; j++) {158m->m_data[i][j] = mynum+i-2*j;159}160}161162multiply(&mats[1], &mats[0], &mats[0]);163}164165static166void167compute(int n)168{169struct matrix tmp;170int i, j;171172for (i=0,j=n-1; i<j; i++,j--) {173multiply(&tmp, &mats[i], &mats[j]);174addeq(&mats[n], &tmp);175}176}177178static179void180computeall(int mynum)181{182int i;183populate_initial_matrixes(mynum);184for (i=2; i<NMATS; i++) {185compute(i);186}187}188189static190int191answer(void)192{193return trace(&mats[NMATS-1]);194}195196static197void198go(int mynum)199{200int r;201202say("Process %d (pid %d) starting computation...\n", mynum,203(int) getpid());204205computeall(mynum);206r = answer();207208if (r != right_answers[mynum]) {209say("Process %d answer %d: FAILED, should be %d\n",210mynum, r, right_answers[mynum]);211exit(1);212}213say("Process %d answer %d: passed\n", mynum, r);214exit(0);215}216217////////////////////////////////////////////////////////////218219static220int221status_is_failure(int status)222{223/* Proper interpretation of Unix exit status */224if (WIFSIGNALED(status)) {225return 1;226}227if (!WIFEXITED(status)) {228/* ? */229return 1;230}231status = WEXITSTATUS(status);232return status != 0;233}234235static236void237makeprocs(void)238{239int i, status, failcount;240pid_t pids[NJOBS];241242printf("Job size approximately %lu bytes\n", (unsigned long) JOBSIZE);243printf("Forking %d jobs; total load %luk\n", NJOBS,244(unsigned long) (NJOBS * JOBSIZE)/1024);245246for (i=0; i<NJOBS; i++) {247pids[i] = fork();248if (pids[i]<0) {249warn("fork");250}251if (pids[i]==0) {252/* child */253go(i);254}255}256257failcount=0;258for (i=0; i<NJOBS; i++) {259if (pids[i]<0) {260failcount++;261}262else {263if (waitpid(pids[i], &status, 0)<0) {264err(1, "waitpid");265}266if (status_is_failure(status)) {267failcount++;268}269}270}271272if (failcount>0) {273printf("%d subprocesses failed\n", failcount);274exit(1);275}276printf("Test complete\n");277}278279int280main()281{282makeprocs();283return 0;284}285286287