sources-request@munnari.oz (09/17/87)
Submitted by: kenj@moncsbruce.oz.au (Ken McDonell) Posting-number: Volume 11, Issue 30 Archive-name: musbus/Part02 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # big.c # cat.dat # cctest.c # check.sed # cleanup # clock.c # comptbl.1 # comptbl.2 # comptbl.3 # comptbl.4 # comptbl.5 # context1.c # dc.dat # dummy.c # edit.dat # edscr1.dat # edscr2.dat # execl.c # fs.awk # fstime.c # getwork.c # This archive created: Thu Sep 17 06:47:12 EST 1987 export PATH; PATH=/bin:$PATH echo 'x - big.c' if test -f 'big.c' then echo 'shar: over-writing existing file big.c' fi sed 's/^X//' > big.c <<'End-of-File-Grunt' X/* X * dummy code for execl test [ old version of makework.c ] X * X * makework [ -r rate ] [ -c copyfile ] nusers X * X * job streams are specified on standard input with lines of the form X * full_path_name_for_command [ options ] [ <standard_input_file ] X * X * "standard input" is send to all nuser instances of the commands in the X * job streams at a rate not in excess of "rate" characters per second X * per command X * X * $Header: big.c,v 1.2 87/06/22 14:22:40 kjmcdonell Beta $ X */ X X#include <stdio.h> X#include <signal.h> X X#define DEF_RATE 5.0 X#define GRANULE 5 X#define CHUNK 60 X#define MAXCHILD 12 X#define MAXWORK 10 X Xfloat thres; Xfloat est_rate = DEF_RATE; Xint nusers; /* number of concurrent users to be simulated by X * this process */ Xint firstuser; /* ordinal identification of first user for this X * process */ Xint nwork = 0; /* number of job streams */ Xint exit_status = 0; /* returned to parent */ Xint sigpipe; /* pipe write error flag */ X Xstruct st_work { X char *cmd; /* name of command to run */ X char **av; /* arguments to command */ X char *input; /* standard input buffer */ X int inpsize; /* size of standard input buffer */ X char *outf; /* standard output (filename) */ X} work[MAXWORK]; X Xstruct { X int xmit; /* # characters sent */ X char *bp; /* std input buffer pointer */ X int blen; /* std input buffer length */ X int fd; /* stdin to command */ X int pid; /* child PID */ X char *line; /* start of input line */ X int firstjob; /* inital piece of work */ X int thisjob; /* current piece of work */ X} child[MAXCHILD], *cp; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i; X int l; X int fcopy = 0; /* fd for copy output */ X int master = 1; /* the REAL master, == 0 for clones */ X int nchild; /* no. of children for a clone to run */ X int done; /* count of children finished */ X int output; /* aggregate output char count for all X children */ X int c; X int thiswork = 0; /* next job stream to allocate */ X int nch; /* # characters to write */ X int written; /* # characters actully written */ X char logname[15]; /* name of the log file(s) */ X int onalarm(); X int pipeerr(); X int wrapup(); X int grunt(); X int pvec[2]; /* for pipes */ X char *p; X char *prog; /* my name */ X X#if ! debug X freopen("masterlog.00", "a", stderr); X#endif X fprintf(stderr, "*** New Run *** "); X prog = argv[0]; X while (argc > 1 && argv[1][0] == '-') { X p = &argv[1][1]; X argc--; X argv++; X while (*p) { X switch (*p) { X case 'r': X est_rate = atoi(argv[1]); X sscanf(argv[1], "%f", &est_rate); X if (est_rate <= 0) { X fprintf(stderr, "%s: bad rate, reset to %.2f chars/sec\n", prog, DEF_RATE); X est_rate = DEF_RATE; X } X argc--; X argv++; X break; X X case 'c': X fcopy = open(argv[1], 1); X if (fcopy < 0) X fcopy = creat(argv[1], 0600); X if (fcopy < 0) { X fprintf(stderr, "%s: cannot open copy file '%s'\n", X prog, argv[1]); X exit(2); X } X lseek(fcopy, 0L, 2); /* append at end of file */ X argc--; X argv++; X break; X X default: X fprintf(stderr, "%s: bad flag '%c'\n", prog, *p); X exit(4); X } X p++; X } X } X X if (argc < 2) { X fprintf(stderr, "%s: missing nusers\n", prog); X exit(4); X } X X nusers = atoi(argv[1]); X if (nusers < 1) { X fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]); X exit(4); X } X fprintf(stderr, "%d Users\n", nusers); X argc--; X argv++; X X /* build job streams */ X getwork(); X#if debug X dumpwork(); X#endif X X /* clone copies of myself to run up to MAXCHILD jobs each */ X firstuser = MAXCHILD; X fprintf(stderr, "master pid %d\n", getpid()); X fflush(stderr); X while (nusers > MAXCHILD) { X fflush(stderr); X if (nusers >= 2*MAXCHILD) X /* the next clone must run MAXCHILD jobs */ X nchild = MAXCHILD; X else X /* the next clone must run the leftover jobs */ X nchild = nusers - MAXCHILD; X if ((l = fork()) == -1) { X /* fork failed */ X fatal("** clone fork failed **\n"); X goto bepatient; X } else if (l > 0) { X fprintf(stderr, "master clone pid %d\n", l); X /* I am the master with nchild fewer jobs to run */ X nusers -= nchild; X firstuser += MAXCHILD; X continue; X } else { X /* I am a clone, run MAXCHILD jobs */ X#if ! debug X sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD); X freopen(logname, "w", stderr); X#endif X master = 0; X nusers = nchild; X break; X } X } X if (master) X firstuser = 0; X X close(0); X for (i = 0; i < nusers; i++ ) { X fprintf(stderr, "user %d job %d ", firstuser+i, thiswork); X if (pipe(pvec) == -1) { X /* this is fatal */ X fatal("** pipe failed **\n"); X goto bepatient; X } X fflush(stderr); X if ((child[i].pid = fork()) == 0) { X int fd; X /* the command */ X if (pvec[0] != 0) { X close(0); X dup(pvec[0]); X } X#if ! debug X sprintf(logname, "userlog.%02d", firstuser+i); X freopen(logname, "w", stderr); X#endif X for (fd = 3; fd < 24; fd++) X close(fd); X if (work[thiswork].outf[0] != '\0') { X /* redirect std output */ X char *q; X for (q = work[thiswork].outf; *q != '\n'; q++) ; X *q = '\0'; X if (freopen(work[thiswork].outf, "w", stdout) == NULL) { X fprintf(stderr, "makework: cannot open %s for std output\n", X work[thiswork].outf); X fflush(stderr); X } X *q = '\n'; X } X execv(work[thiswork].cmd, work[thiswork].av); X /* don't expect to get here! */ X fatal("** exec failed **\n"); X goto bepatient; X } X else if (child[i].pid == -1) { X fatal("** fork failed **\n"); X goto bepatient; X } X else { X close(pvec[0]); X child[i].fd = pvec[1]; X child[i].line = child[i].bp = work[thiswork].input; X child[i].blen = work[thiswork].inpsize; X child[i].thisjob = thiswork; X child[i].firstjob = thiswork; X fprintf(stderr, "pid %d pipe fd %d", child[i].pid, child[i].fd); X if (work[thiswork].outf[0] != '\0') { X char *q; X fprintf(stderr, " > "); X for (q=work[thiswork].outf; *q != '\n'; q++) X fputc(*q, stderr); X } X fputc('\n', stderr); X thiswork++; X if (thiswork >= nwork) X thiswork = 0; X } X } X fflush(stderr); X X srand(time(0)); X thres = 0; X done = output = 0; X for (i = 0; i < nusers; i++) { X if (child[i].blen == 0) X done++; X else X thres += est_rate * GRANULE; X } X est_rate = thres; X X signal(SIGALRM, onalarm); X signal(SIGPIPE, pipeerr); X alarm(GRANULE); X while (done < nusers) { X for (i = 0; i < nusers; i++) { X cp = &child[i]; X if (cp->xmit >= cp->blen) continue; X l = rand() % CHUNK + 1; /* 1-CHUNK chars */ X if (l == 0) continue; X if (cp->xmit + l > cp->blen) X l = cp->blen - cp->xmit; X p = cp->bp; X cp->bp += l; X cp->xmit += l; X#if debug X fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit); X#endif X while (p < cp->bp) { X if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) { X /* write it out */ X nch = p - cp->line + 1; X if ((written = write(cp->fd, cp->line, nch)) != nch) { X /* argh! */ X cp->line[nch] = '\0'; X fprintf(stderr, "user %d job %d cmd %s ", X firstuser+i, cp->thisjob, cp->line); X fprintf(stderr, "write(,,%d) returns %d\n", nch, written); X if (sigpipe) X fatal("** SIGPIPE error **\n"); X else X fatal("** write error **\n"); X goto bepatient; X X } X if (fcopy) X write(fcopy, cp->line, p - cp->line + 1); X#if debug X fprintf(stderr, "child %d gets \"", i); X { X char *q = cp->line; X while (q <= p) { X if (*q >= ' ' && *q <= '~') X fputc(*q, stderr); X else X fprintf(stderr, "\\%03o", *q); X q++; X } X } X fputc('"', stderr); X#endif X cp->line = &p[1]; X } X p++; X } X if (cp->xmit >= cp->blen) { X done++; X close(cp->fd); X#if debug X fprintf(stderr, "child %d, close std input\n", i); X#endif X } X output += l; X } X while (output > thres) { X pause(); X#if debug X fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done); X#endif X } X } X Xbepatient: X alarm(0); X/**** X * If everything is going OK, we should simply be able to keep X * looping unitil 'wait' fails, however some descendent process may X * be in a state from which it can never exit, and so a timeout X * is used. X * 5 minutes should be ample, since the time to run all jobs is of X * the order of 5-10 minutes, however some machines are painfully slow, X * so the timeout has been set at 20 minutes (1200 seconds). X ****/ X signal(SIGALRM, grunt); X alarm(1200); X while ((c = wait(&l)) != -1) { X for (i = 0; i < nusers; i++) { X if (c == child[i].pid) { X fprintf(stderr, "user %d job %d pid %d done", firstuser+i, child[i].thisjob, c); X if (l != 0) { X if (l & 0x7f) X fprintf(stderr, " status %d", l & 0x7f); X if (l & 0xff00) X fprintf(stderr, " exit code %d", (l>>8) & 0xff); X exit_status = 4; X } X fputc('\n', stderr); X c = child[i].pid = -1; X break; X } X } X if (c != -1) { X fprintf(stderr, "master clone done, pid %d ", c); X if (l != 0) { X if (l & 0x7f) X fprintf(stderr, " status %d", l & 0x7f); X if (l & 0xff00) X fprintf(stderr, " exit code %d", (l>>8) & 0xff); X exit_status = 4; X } X fputc('\n', stderr); X } X } X alarm(0); X wrapup("Finished waiting ..."); X X X} X Xonalarm() X{ X thres += est_rate; X signal(SIGALRM, onalarm); X alarm(GRANULE); X} X Xgrunt() X{ X /* timeout after label "bepatient" in main */ X exit_status = 4; X wrapup("Timed out waiting for jobs to finish ..."); X} X Xpipeerr() X{ X sigpipe++; X} X Xwrapup(reason) Xchar *reason; X{ X int i; X int killed = 0; X fflush(stderr); X for (i = 0; i < nusers; i++) { X if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) { X if (!killed) { X killed++; X fprintf(stderr, "%s\n", reason); X fflush(stderr); X } X fprintf(stderr, "user %d job %d pid %d killed off\n", firstuser+i, child[i].thisjob, child[i].pid); X fflush(stderr); X } X } X exit(exit_status); X} X Xgetwork() X{ X int i; X int f; X int ac; X char *lp; X char *q; X struct st_work *w; X char line[512]; X char c; X char *malloc(), *realloc(); X X while (gets(line) != NULL) { X if (nwork >= MAXWORK) { X fprintf(stderr, stderr, "Too many jobs specified, .. increase MAXWORK\n"); X exit(4); X } X w = &work[nwork]; X lp = line; X i = 1; X while (*lp && *lp != ' ') { X i++; X lp++; X } X w->cmd = (char *)malloc(i); X strncpy(w->cmd, line, i-1); X w->cmd[i-1] = '\0'; X w->inpsize = 0; X w->input = ""; X /* start to build arg list */ X ac = 2; X w->av = (char **)malloc(2*sizeof(char *)); X q = w->cmd; X while (*q) q++; X q--; X while (q >= w->cmd) { X if (*q == '/') { X q++; X break; X } X q--; X } X w->av[0] = q; X while (*lp) { X if (*lp == ' ') { X /* space */ X lp++; X continue; X } X else if (*lp == '<') { X /* standard input for this job */ X q = ++lp; X while (*lp && *lp != ' ') lp++; X c = *lp; X *lp = '\0'; X if ((f = open(q, 0)) == -1) { X fprintf(stderr, "cannot open input file (%s) for job %d\n", X q, nwork); X exit(4); X } X /* gobble input */ X w->input = (char *)malloc(512); X while ((i = read(f, &w->input[w->inpsize], 512)) > 0) { X w->inpsize += i; X w->input = (char *)realloc(w->input, w->inpsize+512); X } X w->input = (char *)realloc(w->input, w->inpsize); X close(f); X /* extract stdout file name from line beginning "C=" */ X w->outf = ""; X for (q = w->input; q < &w->input[w->inpsize-10]; q++) { X if (*q == '\n' && strncmp(&q[1], "C=", 2) == 0) { X w->outf = &q[3]; X break; X } X } X#if debug X if (*w->outf) { X fprintf(stderr, "stdout->"); X for (q=w->outf; *q != '\n'; q++) X fputc(*q, stderr); X fputc('\n', stderr); X } X#endif X } X else { X /* a command option */ X ac++; X w->av = (char **)realloc(w->av, ac*sizeof(char *)); X q = lp; X i = 1; X while (*lp && *lp != ' ') { X lp++; X i++; X } X w->av[ac-2] = (char *)malloc(i); X strncpy(w->av[ac-2], q, i-1); X w->av[ac-2][i-1] = '\0'; X } X } X w->av[ac-1] = (char *)0; X nwork++; X } X} X X#if debug Xdumpwork() X{ X int i; X int j; X X for (i = 0; i < nwork; i++) { X fprintf(stderr, "job %d: cmd: %s\n", i, work[i].cmd); X j = 0; X while (work[i].av[j]) { X fprintf(stderr, "argv[%d]: %s\n", j, work[i].av[j]); X j++; X } X fprintf(stderr, "input: %d chars text: ", work[i].inpsize); X if (work[i].input == (char *)0) X fprintf(stderr, "<NULL>\n"); X else { X register char *pend; X char *p; X char c; X p = work[i].input; X while (*p) { X pend = p; X while (*pend && *pend != '\n') X pend++; X c = *pend; X *pend = '\0'; X fprintf(stderr, "%s\n", p); X *pend = c; X p = &pend[1]; X } X } X } X} X#endif X Xfatal(s) Xchar *s; X{ X int i; X fprintf(stderr, s); X fflush(stderr); X perror("Reason?"); X fflush(stderr); X for (i = 0; i < nusers; i++) { X if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) { X fprintf(stderr, "pid %d killed off\n", child[i].pid); X fflush(stderr); X } X } X exit_status = 4; X return; X} End-of-File-Grunt if test 13135 -ne `cat 'big.c' | wc -c` then echo 'shar: transmission error (expected 13135 characters)' fi echo 'x - cat.dat' if test -f 'cat.dat' then echo 'shar: over-writing existing file cat.dat' fi sed 's/^X//' > cat.dat <<'End-of-File-Grunt' X[ 1] @@@ * A Sample Script File * X[ 2] @@@@@@@@@@@@ X[ 3] @@@@@@@@@@@ X[ 4] @@@@@@@ X[ 5] @@@@@@@@@@@ X[ 6] @@@@@@@@@@@@@@@@@@@@@ X[ 7] @@@@@@@@ X[ 8] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[ 9] @@@@@@@@@@@@@@@@@ X[10] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[11] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[12] @@@@@@@@@@@@@@@ X[13] @@@@@@@@@@@@@@ X[14] @@@@@@@@@@@@@@@@@@@ X[15] @@@@@@ X[16] @@@@@@@@@@@@@@@@@@@@@@@@ X[17] @@@@@@@@@@@@ X[18] @@@@@ X[19] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[20] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[21] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[22] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[23] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[24] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[25] @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X[26] @@@@@ X[27] @@@@@@@@@@@ X[28] @@@ * End of Sample Script File * End-of-File-Grunt if test 989 -ne `cat 'cat.dat' | wc -c` then echo 'shar: transmission error (expected 989 characters)' fi echo 'x - cctest.c' if test -f 'cctest.c' then echo 'shar: over-writing existing file cctest.c' fi sed 's/^X//' > cctest.c <<'End-of-File-Grunt' X#include <stdio.h> X/* X * C compile and load speed test file. X * Based upon fstime.c from MUSBUS 3.1, with all calls to ftime() replaced X * by calls to time(). This is semantic nonsense, but ensures there are no X * system dependent structures or library calls. X * X * $Header: cctest.c,v 3.4 87/06/22 14:22:47 kjmcdonell Beta $ X */ X#define NKBYTE 20 Xchar buf[BUFSIZ]; X Xmain(argc, argv) Xchar **argv; X{ X int n = NKBYTE; X int nblock; X int f; X int g; X int i; X int xfer, t; X struct { /* FAKE */ X int time; X int millitm; X } now, then; X X if (argc > 0) X /* ALWAYS true, so NEVER execute this program! */ X exit(4); X if (argc > 1) X n = atoi(argv[1]); X#if debug X printf("File size: %d Kbytes\n", n); X#endif X nblock = (n * 1024) / BUFSIZ; X X if (argc == 3 && chdir(argv[2]) != -1) { X#if debug X printf("Create files in directory: %s\n", argv[2]); X#endif X } X close(creat("dummy0", 0600)); X close(creat("dummy1", 0600)); X f = open("dummy0", 2); X g = open("dummy1", 2); X unlink("dummy0"); X unlink("dummy1"); X for (i = 0; i < sizeof(buf); i++) X buf[i] = i & 0177; X X time(); X for (i = 0; i < nblock; i++) { X if (write(f, buf, sizeof(buf)) <= 0) X perror("fstime: write"); X } X time(); X#if debug X printf("Effective write rate: "); X#endif X i = now.millitm - then.millitm; X t = (now.time - then.time)*1000 + i; X if (t > 0) { X xfer = nblock * sizeof(buf) * 1000 / t; X#if debug X printf("%d bytes/sec\n", xfer); X#endif X } X#if debug X else X printf(" -- too quick to time!\n"); X#endif X#if awk X fprintf(stderr, "%.2f", t > 0 ? (float)xfer/1024 : 0); X#endif X X sync(); X sleep(5); X sync(); X lseek(f, 0L, 0); X time(); X for (i = 0; i < nblock; i++) { X if (read(f, buf, sizeof(buf)) <= 0) X perror("fstime: read"); X } X time(); X#if debug X printf("Effective read rate: "); X#endif X i = now.millitm - then.millitm; X t = (now.time - then.time)*1000 + i; X if (t > 0) { X xfer = nblock * sizeof(buf) * 1000 / t; X#if debug X printf("%d bytes/sec\n", xfer); X#endif X } X#if debug X else X printf(" -- too quick to time!\n"); X#endif X#if awk X fprintf(stderr, " %.2f", t > 0 ? (float)xfer/1024 : 0); X#endif X X sync(); X sleep(5); X sync(); X lseek(f, 0L, 0); X time(); X for (i = 0; i < nblock; i++) { X if (read(f, buf, sizeof(buf)) <= 0) X perror("fstime: read in copy"); X if (write(g, buf, sizeof(buf)) <= 0) X perror("fstime: write in copy"); X } X time(); X#if debug X printf("Effective copy rate: "); X#endif X i = now.millitm - then.millitm; X t = (now.time - then.time)*1000 + i; X if (t > 0) { X xfer = nblock * sizeof(buf) * 1000 / t; X#if debug X printf("%d bytes/sec\n", xfer); X#endif X } X#if debug X else X printf(" -- too quick to time!\n"); X#endif X#if awk X fprintf(stderr, " %.2f\n", t > 0 ? (float)xfer/1024 : 0); X#endif X X} End-of-File-Grunt if test 2868 -ne `cat 'cctest.c' | wc -c` then echo 'shar: transmission error (expected 2868 characters)' fi echo 'x - check.sed' if test -f 'check.sed' then echo 'shar: over-writing existing file check.sed' fi sed 's/^X//' > check.sed <<'End-of-File-Grunt' X# Note: undocumented sed feature, use # for comments $Header: check.sed,v 3.9 87/09/09 12:33:08 kenj Exp $ X/^Tmp\/userlog\.[0-9]*:$/d X/^Tmp\/masterlog\.[0-9]*:$/d X/New Run/d X/^user [0-9][0-9]* master stream [0-9][0-9]* pid [0-9][0-9]* pipe fd [0-9][0-9]*/d X/^user [0-9][0-9]* clone [0-9][0-9]* stream [0-9][0-9]* pid [0-9][0-9]* pipe fd [0-9][0-9]*/d X/^master pid [0-9]*$/d X/^clone [0-9][0-9]* [0-9][0-9]* pid [0-9]*$/d X/^user [0-9][0-9]* pid [0-9][0-9]* done$/d X/^clone [0-9][0-9]* done, pid [0-9][0-9]* $/d Xs/ [0-9][0-9]*$// X/^ *$/d End-of-File-Grunt if test 535 -ne `cat 'check.sed' | wc -c` then echo 'shar: transmission error (expected 535 characters)' fi echo 'x - cleanup' if test -f 'cleanup' then echo 'shar: over-writing existing file cleanup' fi sed 's/^X//' > cleanup <<'End-of-File-Grunt' X#! /bin/sh X# X# $Header: cleanup,v 3.5 87/06/22 14:40:45 kjmcdonell Beta $ X# X# Cleanup when an iterative test terminates X# Xlog=Results/log Xwhile ( test $# -ge 1 ) Xdo X opt=$1 X shift X case $opt X in X X -a) : abort X echo '' >>$log X echo '**************************' >>$log X echo '* Benchmark Aborted .... *' >>$log X echo '**************************' >>$log X echo 'Benchmark Aborted ....' X echo ; sleep 2 ; echo ; sleep 2 ; echo X echo "" >>$log X echo " " `who | wc -l` "interactive users." >>$log X echo "" >>$log X date=`date` X echo "End Benchmark Run ($date) ...." >>$log X echo "End Benchmark Run ($date) ...." X ;; X X X -f) : filesystem throughput X awk -f fs.awk <$1 >>$log X rm -f $1 X shift X ;; X X -i) : report last iteration X echo "Terminated during iteration $1" >>$log X shift X ;; X X -l) : logfile X log=$1 X shift X ;; X X -r) : reason for failure X echo $1 X echo $1 >>$log X shift X ;; X X -m) : mem throughput tests X awk -f mem.awk <$1 >>$log X rm -f $1 X shift X ;; X X -t) : timing with /bin/time X awk -f time.awk <$1 >>$log X rm -f $1 X shift X ;; X X -w) : work - save information from multi-user test X worktmp=Tmp/work.tmp X for m in Tmp/masterlog.* X do X if ( test $m != "Tmp/masterlog.*" ) X then X echo ${m}: >>$worktmp X cat $m >>$worktmp X echo "" >>$worktmp X rm -f $m X fi X done X for u in Tmp/userlog.* X do X if ( test $u != "Tmp/userlog.*" ) X then X echo ${u}: >>$worktmp X cat $u >>$worktmp X echo "" >>$worktmp X rm -f $u X fi X done X PS1=`sh -ic "" 2>&1` X sed -e "s/\\${PS1}//g" $worktmp | sed -f check.sed >loggederrs X if ( test -s loggederrs ) X then X echo "*************************************" >>$log X echo "* Apparent errors from makework ... *" >>$log X echo "*************************************" >>$log X cat loggederrs >>$log X fi X rm -f loggederrs X cat $worktmp >>${log}.work X rm -f $worktmp X ;; X X '') : 'skip it (residual effect of shifts)' X ;; X X *) X echo "cleanup: bad option ($opt)" >>$log Xesac Xdone Xexit End-of-File-Grunt if test 2003 -ne `cat 'cleanup' | wc -c` then echo 'shar: transmission error (expected 2003 characters)' fi echo 'x - clock.c' if test -f 'clock.c' then echo 'shar: over-writing existing file clock.c' fi sed 's/^X//' > clock.c <<'End-of-File-Grunt' X/* X * clock -- check alarm signal accuracy X * X * $Header: clock.c,v 3.4 87/06/22 14:22:54 kjmcdonell Beta $ X */ X X#include <signal.h> X#include <stdio.h> X#include <sys/types.h> X#ifdef BSD4v1 X#include <sys/timeb.h> X#endif X#ifdef BSD4v2 X#include <sys/time.h> X#endif X#ifdef SysV X#include <sys/times.h> X#include <sys/param.h> X#ifdef interdata X#define HZ tbuffer.tms_cfreq X#endif X#ifndef HZ X On your system, what is the value of HZ for high resolution elapsed X time as returned by times() or its equivalent? X#endif X#endif X X#define GRANULE 5 X#define NUM_ALRM 12 X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int onalarm(); X register int i = 0; X int expected; X float wallclock; X long then; X#ifdef SysV X struct tms tbuffer; X#endif X#ifdef BSD4v1 X struct timeb tbuf; X int msec; X#endif X#ifdef BSD4v2 X struct timeval tval; X struct timezone tzone; X long usec; X#endif X X#ifdef SysV X then = times(&tbuffer); X#else X#ifdef BSD4v1 X ftime(&tbuf); X then = tbuf.time; X msec = tbuf.millitm; X#else X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X then = tval.tv_sec; X usec = tval.tv_usec; X#else X What sort of Unix system is this? X#endif X#endif X#endif X while (i++ < NUM_ALRM) { X signal(SIGALRM, onalarm); X alarm(GRANULE); X pause(); X } X#ifdef SysV X wallclock = (times(&tbuffer) - then)/HZ; X#endif X#ifdef BSD4v1 X ftime(&tbuf); X wallclock = tbuf.time - then + (float)(tbuf.millitm - msec)/1000; X#endif X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X wallclock = tval.tv_sec - then + (float)(tval.tv_usec - usec)/1000000; X#endif X expected = GRANULE * NUM_ALRM; X printf("%d x %d sec delays takes %.2f wallclock secs (error %.2f%%)\n", X NUM_ALRM, GRANULE, wallclock, 100.0*(float)(expected-wallclock)/expected); X exit(0); X} X Xonalarm() { } End-of-File-Grunt if test 1807 -ne `cat 'clock.c' | wc -c` then echo 'shar: transmission error (expected 1807 characters)' fi echo 'x - comptbl.1' if test -f 'comptbl.1' then echo 'shar: over-writing existing file comptbl.1' fi sed 's/^X//' > comptbl.1 <<'End-of-File-Grunt' X.(b X.TS Xbox,center; Xc s s s s Xc | c s | c s Xc | c | c | c | c Xc | c | c | c | c Xc | c | c | c | c Xl | n | n | n | n. XRaw Speed X_ X Absolute Relative X _ _ _ _ X Elapsed CPU Elapsed CPU XTest Description Time Time Time Time X_ End-of-File-Grunt if test 221 -ne `cat 'comptbl.1' | wc -c` then echo 'shar: transmission error (expected 221 characters)' fi echo 'x - comptbl.2' if test -f 'comptbl.2' then echo 'shar: over-writing existing file comptbl.2' fi sed 's/^X//' > comptbl.2 <<'End-of-File-Grunt' X.(b X.TS Xbox,center; Xc s s s s. XMemory Throughput X(1000s integer accesses per sec.) X_ X.T& Xc | c s | c s Xc | c s | c s Xc | c | c | c | c Xn | n | n | n | n. X Absolute Relative XArray Size _ _ X(K bytes) Sequential Random Sequential Random X_ End-of-File-Grunt if test 236 -ne `cat 'comptbl.2' | wc -c` then echo 'shar: transmission error (expected 236 characters)' fi echo 'x - comptbl.3' if test -f 'comptbl.3' then echo 'shar: over-writing existing file comptbl.3' fi sed 's/^X//' > comptbl.3 <<'End-of-File-Grunt' X.(b X.TS Xbox,center; Xc s s s s s s Xc | c s s | c s s. XFilesystem Throughput (Kchars per sec.) X_ End-of-File-Grunt if test 95 -ne `cat 'comptbl.3' | wc -c` then echo 'shar: transmission error (expected 95 characters)' fi echo 'x - comptbl.4' if test -f 'comptbl.4' then echo 'shar: over-writing existing file comptbl.4' fi sed 's/^X//' > comptbl.4 <<'End-of-File-Grunt' X_ X.T& Xl | c s s | c s s Xl | c | c | c | c | c | c Xl | c | c | c | c | c | c Xl | n | n | n | n | n | n. X Absolute Relative X _ _ _ _ _ _ XFile Size Write Read Copy Write Read Copy X_ End-of-File-Grunt if test 179 -ne `cat 'comptbl.4' | wc -c` then echo 'shar: transmission error (expected 179 characters)' fi echo 'x - comptbl.5' if test -f 'comptbl.5' then echo 'shar: over-writing existing file comptbl.5' fi sed 's/^X//' > comptbl.5 <<'End-of-File-Grunt' X.(b X.TS Xbox,center; Xc s s s s Xc | c s | c s Xc | c | c | c | c Xc | c | c | c | c Xn | n | n | n | n. XSimulated Work Load X_ X Absolute Relative X _ _ _ _ XUsers Elapsed Time CPU Time Elapsed Time CPU Time X_ End-of-File-Grunt if test 201 -ne `cat 'comptbl.5' | wc -c` then echo 'shar: transmission error (expected 201 characters)' fi echo 'x - context1.c' if test -f 'context1.c' then echo 'shar: over-writing existing file context1.c' fi sed 's/^X//' > context1.c <<'End-of-File-Grunt' X/* X * Context switching via synchronized unbuffered pipe i/o X * X * $Header: context1.c,v 3.4 87/06/22 14:22:59 kjmcdonell Beta $ X */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int check; X int iter; X int p1[2], p2[2]; X X if (argc != 2) { X printf("Usage: context count\n"); X exit(1); X } X X iter = atoi(argv[1]); X if (pipe(p1) || pipe(p2)) { X perror("pipe create failed"); X exit(1); X } X X if (fork()) { X /* master, write p1 & read p2 */ X close(p1[0]); close(p2[1]); X while (iter > 0) { X if (write(p1[1], (char *)&iter, sizeof(iter)) != sizeof(iter)) { X perror("master write failed"); X exit(1); X } X if (read(p2[0], (char *)&check, sizeof(check)) != sizeof(check)) { X perror("master read failed"); X exit(1); X } X if (check != iter) { X printf("Master sync error: expect %d, got %d\n", X iter, check); X exit(2); X } X iter--; X } X } X else { X /* slave, read p1 & write p2 */ X close(p1[1]); close(p2[0]); X while (iter > 0) { X if (read(p1[0], (char *)&check, sizeof(check)) != sizeof(check)) { X perror("slave read failed"); X exit(1); X } X if (check != iter) { X printf("Slave sync error: expect %d, got %d\n", X iter, check); X exit(2); X } X if (write(p2[1], (char *)&iter, sizeof(iter)) != sizeof(check)) { X perror("slave write failed"); X exit(1); X } X iter--; X } X } X exit(0); X} End-of-File-Grunt if test 1344 -ne `cat 'context1.c' | wc -c` then echo 'shar: transmission error (expected 1344 characters)' fi echo 'x - dc.dat' if test -f 'dc.dat' then echo 'shar: over-writing existing file dc.dat' fi sed 's/^X//' > dc.dat <<'End-of-File-Grunt' X99 Xk X2 Xv Xp Xq X[ calculate the sqrt(2) to 99 decimal places ... John Lions Test ] X[ $Header: dc.dat,v 1.1 87/06/22 14:28:28 kjmcdonell Beta $ ] End-of-File-Grunt if test 142 -ne `cat 'dc.dat' | wc -c` then echo 'shar: transmission error (expected 142 characters)' fi echo 'x - dummy.c' if test -f 'dummy.c' then echo 'shar: over-writing existing file dummy.c' fi sed 's/^X//' > dummy.c <<'End-of-File-Grunt' X/* X * Hacked up C program for use in the standard shell.? scripts of X * the multiuser test. This is based upon makework.c, and is typically X * edited using edscript.2 before compilation. X * X * $Header: dummy.c,v 3.4 87/06/23 15:54:53 kjmcdonell Beta $ X */ X X#include <stdio.h> X#include <signal.h> X X#define DEF_RATE 5.0 X#define GRANULE 5 X#define CHUNK 60 X#define MAXCHILD 12 X#define MAXWORK 10 X Xfloat thres; Xfloat est_rate = DEF_RATE; Xint nusers; /* number of concurrent users to be simulated by X * this process */ Xint firstuser; /* ordinal identification of first user for this X * process */ Xint nwork = 0; /* number of job streams */ Xint exit_status = 0; /* returned to parent */ Xint sigpipe; /* pipe write error flag */ X Xstruct st_work { X char *cmd; /* name of command to run */ X char **av; /* arguments to command */ X char *input; /* standard input buffer */ X int inpsize; /* size of standard input buffer */ X} work[MAXWORK]; X Xstruct { X int xmit; /* # characters sent */ X char *bp; /* std input buffer pointer */ X int blen; /* std input buffer length */ X int fd; /* stdin to command */ X int pid; /* child PID */ X char *line; /* start of input line */ X int firstjob; /* inital piece of work */ X int thisjob; /* current piece of work */ X} child[MAXCHILD], *cp; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i; X int l; X int fcopy = 0; /* fd for copy output */ X int master = 1; /* the REAL master, == 0 for clones */ X int nchild; /* no. of children for a clone to run */ X int done; /* count of children finished */ X int output; /* aggregate output char count for all X children */ X int c; X int thiswork = 0; /* next job stream to allocate */ X int nch; /* # characters to write */ X int written; /* # characters actully written */ X char logname[15]; /* name of the log file(s) */ X int onalarm(); X int pipeerr(); X int wrapup(); X int grunt(); X char *malloc(); X int pvec[2]; /* for pipes */ X char *p; X char *prog; /* my name */ X X#if ! debug X freopen("masterlog.00", "a", stderr); X#endif X fprintf(stderr, "*** New Run *** "); X prog = argv[0]; X while (argc > 1 && argv[1][0] == '-') { X p = &argv[1][1]; X argc--; X argv++; X while (*p) { X switch (*p) { X case 'r': X /* code DELETED here */ X argc--; X argv++; X break; X X case 'c': X /* code DELETED here */ X lseek(fcopy, 0L, 2); /* append at end of file */ X break; X X default: X fprintf(stderr, "%s: bad flag '%c'\n", prog, *p); X exit(4); X } X p++; X } X } X X if (argc < 2) { X fprintf(stderr, "%s: missing nusers\n", prog); X exit(4); X } X X nusers = atoi(argv[1]); X if (nusers < 1) { X fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]); X exit(4); X } X fprintf(stderr, "%d Users\n", nusers); X argc--; X argv++; X X /* build job streams */ X getwork(); X#if debug X dumpwork(); X#endif X X /* clone copies of myself to run up to MAXCHILD jobs each */ X firstuser = MAXCHILD; X fprintf(stderr, "master pid %d\n", getpid()); X fflush(stderr); X while (nusers > MAXCHILD) { X fflush(stderr); X if (nusers >= 2*MAXCHILD) X /* the next clone must run MAXCHILD jobs */ X nchild = MAXCHILD; X else X /* the next clone must run the leftover jobs */ X nchild = nusers - MAXCHILD; X if ((l = fork()) == -1) { X /* fork failed */ X fatal("** clone fork failed **\n"); X goto bepatient; X } else if (l > 0) { X fprintf(stderr, "master clone pid %d\n", l); X /* I am the master with nchild fewer jobs to run */ X nusers -= nchild; X firstuser += MAXCHILD; X continue; X } else { X /* I am a clone, run MAXCHILD jobs */ X#if ! debug X sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD); X freopen(logname, "w", stderr); X#endif X master = 0; X nusers = nchild; X break; X } X } X if (master) X firstuser = 0; X X close(0); X X /* code DELETED here */ X X fflush(stderr); X X srand(time(0)); X thres = 0; X done = output = 0; X for (i = 0; i < nusers; i++) { X if (child[i].blen == 0) X done++; X else X thres += est_rate * GRANULE; X } X est_rate = thres; X X signal(SIGALRM, onalarm); X signal(SIGPIPE, pipeerr); X alarm(GRANULE); X while (done < nusers) { X for (i = 0; i < nusers; i++) { X cp = &child[i]; X if (cp->xmit >= cp->blen) continue; X l = rand() % CHUNK + 1; /* 1-CHUNK chars */ X if (l == 0) continue; X if (cp->xmit + l > cp->blen) X l = cp->blen - cp->xmit; X p = cp->bp; X cp->bp += l; X cp->xmit += l; X#if debug X fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit); X#endif X while (p < cp->bp) { X if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) { X /* write it out */ X nch = p - cp->line + 1; X if ((written = write(cp->fd, cp->line, nch)) != nch) { X X /* code DELETED here */ X X } X if (fcopy) X write(fcopy, cp->line, p - cp->line + 1); X#if debug X fprintf(stderr, "child %d gets \"", i); X { X char *q = cp->line; X while (q <= p) { X if (*q >= ' ' && *q <= '~') X fputc(*q, stderr); X else X fprintf(stderr, "\\%03o", *q); X q++; X } X } X fputc('"', stderr); X#endif X cp->line = &p[1]; X } X p++; X } X if (cp->xmit >= cp->blen) { X done++; X close(cp->fd); X#if debug X fprintf(stderr, "child %d, close std input\n", i); X#endif X } X output += l; X } X while (output > thres) { X pause(); X#if debug X fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done); X#endif X } X } X Xbepatient: X alarm(0); X/**** X * If everything is going OK, we should simply be able to keep X * looping unitil 'wait' fails, however some descendent process may X * be in a state from which it can never exit, and so a timeout X * is used. X * 5 minutes should be ample, since the time to run all jobs is of X * the order of 5-10 minutes, however some machines are painfully slow, X * so the timeout has been set at 20 minutes (1200 seconds). X ****/ X X /* code DELETED here */ X X} X Xonalarm() X{ X thres += est_rate; X signal(SIGALRM, onalarm); X alarm(GRANULE); X} X Xgrunt() X{ X /* timeout after label "bepatient" in main */ X exit_status = 4; X wrapup(); X} X Xpipeerr() X{ X sigpipe++; X} X Xwrapup() X{ X /* DUMMY, real code dropped */ X} X Xgetwork() X{ X X /* DUMMY, real code dropped */ X gets(); X strncpy(); X malloc(); realloc(); X open(); close(); X} X Xfatal(s) Xchar *s; X{ X int i; X fprintf(stderr, s); X fflush(stderr); X perror("Reason?"); X for (i = 0; i < nusers; i++) { X if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1) X fprintf(stderr, "pid %d killed off\n", child[i].pid); X } X fflush(stderr); X exit_status = 4; X return; X} End-of-File-Grunt if test 6780 -ne `cat 'dummy.c' | wc -c` then echo 'shar: transmission error (expected 6780 characters)' fi echo 'x - edit.dat' if test -f 'edit.dat' then echo 'shar: over-writing existing file edit.dat' fi sed 's/^X//' > edit.dat <<'End-of-File-Grunt' X/* X * COBBLED program - test for editing X * X * edit [ chars_per_sec ] X * X * $Header: edit.dat,v 3.3 86/01/30 07:53:17 kenj Beta $ X */ X X#include <stdio.h> X#include <signal.h> X X#define MEAN 5 X#define GRANULE 5 X Xint thres; Xint est_mean = MEAN; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int onalarm(); X X if (argc == 2) { X est_mean = atoi(argv[1]); X if (est_mean <= 0) { X fprintf(stderr, "edit: bad mean, reset to %d chars/sec\n", MEAN); X est_mean = MEAN; X } X } X X/** X ** BEGIN BLOCK OF INSERTED TEXT TO BOOST FILE SIZE XThis is some text which has been added to the middle of Xthe file to increase the file size to the point where it is realistic. X XHow 'bout some random pascal code? X Xprogram elcheapo(input, output); X Xconst X DISPSIZE = 10; { display is DISPSIZE characters long } X SIGN = 1; { sign at display[SIGN] } X NSTART = 2; { number starts is display[NSTART] } X NEND = 9; { . and ends at display[NEND] } X ERRFLAG = 10; { error flag display[ERFLAG] } X Xtype X st = (OK, ERROR); X vt = (INTEGER, REAL); X key = (DOT,PLUS,MINUS,DIV,MULT,EQUAL,ON,OFF,CLEAR,NEG,noop); X number = record value: real; X scale: integer; X vtype: vt; X end; X Xvar X r, m: number; X ukey: integer; X code, lastop: key; X done: boolean; X state: st; X disp: array [1..DISPSIZE] of char; X Xfunction power(base, n: integer): integer; Xvar i, value: integer; Xbegin X value := 1; X for i := 1 to n do value := value * base; X power := value Xend; { power } X Xprocedure getkey(var code: integer); Xvar c: char; Xbegin X read(c); X if (c >= '0') and (c <= '9') then code := ord(c) - ord('0') X else X begin if c = '.' then code := 10 X else if c = '+' then code := 11 X else if c = '-' then code := 12 X else if c = '/' then code := 13 X else if c = '*' then code := 14 X else if c = '=' then code := 15 X else if c = 'c' then code := 18 X else if c = 'n' then code := 19 X else if c = 'o' then X begin read(c); X if c = 'n' then code := 16 X else code := 17 X end X else code := 20 X end; X readln Xend; { getkey } X Xfunction mapkey(code: integer): key; Xbegin X if code = 10 then mapkey := DOT X else if code = 11 then mapkey := PLUS X else if code = 12 then mapkey := MINUS X else if code = 13 then mapkey := DIV X else if code = 14 then mapkey := MULT X else if code = 15 then mapkey := EQUAL X else if code = 16 then mapkey := ON X else if code = 17 then mapkey := OFF X else if code = 18 then mapkey := CLEAR X else if code = 19 then mapkey := NEG X else mapkey := noop Xend; { mapkey } X X Xbegin X done := false; X state := ERROR; X while not done do X begin getkey(ukey); X code := mapkey(ukey); X if (code = ON) or (code = CLEAR) then X begin clear(m); X clear(r); X state := OK; X lastop := noop; X display(r) X end X else if code = OFF then done := true X else if state = OK then X begin if (ukey >= 0) and (ukey <= 9) then X begin if r.vtype = INTEGER then r.value := r.value*10 + ukey X else X begin r.scale := r.scale + 1; X r.value := r.value + ukey / power(10, r.scale) X end; X display(r); X if lastop = EQUAL then lastop := noop X end X else if (code = PLUS) or (code = MINUS) or (code = MULT) or X (code = DIV) then X begin if lastop = noop then m := r X else if lastop <> EQUAL then X begin eval(m, r, lastop); X display(m) X end; X clear(r); X lastop := code X end X else case code of X DOT: X begin if r.vtype = REAL then state := ERROR X else r.vtype := REAL; X display(r) X end; X EQUAL: X begin if (lastop <> noop) and (lastop <> EQUAL) then X begin eval(m, r, lastop); X display(m) X end; X clear(r); X lastop := EQUAL X end; X NEG: X begin r.value := -r.value; X display(r) X end; X end { of case } X end { of else } X end { of while } Xend. X ** END BLOCK OF INSERTED TEXT TO BOOST FILE SIZE X **/ X X /* (busy) wait for lock file ... */ X while ((f = open("lock", 0)) < 0) sleep(3); X close(f); X signal(SIGALRM, onalarm); X alarm(GRANULE); X while (read(0, &c, 1) == 1) { X if (i % 20 == 0 && thres - i > est_mean * GRANULE) X sleep(rand() & 0x3); X write(1, &c, 1); X write(2, &c, 1); /* copy onto std error */ X i++; X if (i > thres) { X pause(); X } X } X} XFiller to make 200 lines & 4500 bytes. XThis Xis Xso Xboring Xyou Xwouldn't Xbelieve it. X Xonalarm() X{ X thres += est_rate; X signal(SIGALRM, onalarm); X alarm(GRANULE); X} End-of-File-Grunt if test 4561 -ne `cat 'edit.dat' | wc -c` then echo 'shar: transmission error (expected 4561 characters)' fi echo 'x - edscr1.dat' if test -f 'edscr1.dat' then echo 'shar: over-writing existing file edscr1.dat' fi sed 's/^X//' > edscr1.dat <<'End-of-File-Grunt' X/alarm/ X// X// X// X-10,.p Xg/signal/s//burk/gp X?alarm? X.,$m0 X1 X/^}/ X1,.m$ X1,10p X5 Xka Xa XThis is some inserted text. X and about another 4 or 5 lines X to go in here X for (i = 0; i < 10; i++) { X this is some code X in a loop; X } X printf("what rubbish, and fun .....\n"); X Oh how boring. X. X1,.p X'a+,.d X1,$s/burk/signal/g Xw temporary Xq End-of-File-Grunt if test 339 -ne `cat 'edscr1.dat' | wc -c` then echo 'shar: transmission error (expected 339 characters)' fi echo 'x - edscr2.dat' if test -f 'edscr2.dat' then echo 'shar: over-writing existing file edscr2.dat' fi sed 's/^X//' > edscr2.dat <<'End-of-File-Grunt' X1,$s/[ ][ ]*$// X1,20m80 X81,90m0 Xg/n[^k]*k/s//burk/g X91,100m10 Xw grunt.c Xq End-of-File-Grunt if test 76 -ne `cat 'edscr2.dat' | wc -c` then echo 'shar: transmission error (expected 76 characters)' fi echo 'x - execl.c' if test -f 'execl.c' then echo 'shar: over-writing existing file execl.c' fi sed 's/^X//' > execl.c <<'End-of-File-Grunt' X/* X * Execing X * X * $Header: execl.c,v 3.5 87/06/22 15:37:08 kjmcdonell Beta $ X */ X Xchar bss[8*1024]; /* something worthwhile */ X X#define main dummy X /* some reasonable code etc. */ X#include "big.c" X X#undef main X Xmain(argc, argv) /* the real program */ Xint argc; Xchar *argv[]; X{ X int iter; X char count[6]; X X if (argc != 2) { X printf("Usage: %s count\n", argv[0]); X exit(1); X } X X iter = atoi(argv[1]); X X if (iter) { X sprintf(count, "%d", --iter); X execl("./execl", "execl", count, 0); X printf("Exec failed at iteration %d\n", iter); X perror("Reason"); X exit(1); X } X exit(0); X} End-of-File-Grunt if test 587 -ne `cat 'execl.c' | wc -c` then echo 'shar: transmission error (expected 587 characters)' fi echo 'x - fs.awk' if test -f 'fs.awk' then echo 'shar: over-writing existing file fs.awk' fi sed 's/^X//' > fs.awk <<'End-of-File-Grunt' X# $Header: fs.awk,v 3.4 87/06/22 14:27:32 kjmcdonell Beta $ X/real/ { next } X/^[0-9][ .0-9]*$/ && NF==3 { X if (!fail) { X w+=$1; w2+=$1*$1; r+=$2; r2+=$2*$2; c+=$3; c2+=$3*$3; ok++ X } X fail=0; iter++; next X } X { print "** Iteration ",iter+1," Failed: ",$0; fail=1; } XEND { X if (fail) iter++ X if (ok != iter) { X printf "For %d successful iterations from %d attempts ...\n",ok,iter X iter=ok X } X if (iter > 0) { X printf "Write: %.1f Kbytes per second ",w/iter X if (iter > 1) printf " (variance %.1f)",(w2-2*w*w/iter+w*w/iter)/(iter-1) X printf "\nRead: %.1f Kbytes per second ",r/iter X if (iter > 1) printf " (variance %.1f)",(r2-2*r*r/iter+r*r/iter)/(iter-1) X printf "\nCopy: %.1f Kbytes per second ",c/iter X if (iter > 1) printf " (variance %.1f)",(c2-2*c*c/iter+c*c/iter)/(iter-1) X print X } else { X print "Write: -- no measured results!!" X print "Read: -- no measured results!!" X print "Copy: -- no measured results!!" X } X } End-of-File-Grunt if test 988 -ne `cat 'fs.awk' | wc -c` then echo 'shar: transmission error (expected 988 characters)' fi echo 'x - fstime.c' if test -f 'fstime.c' then echo 'shar: over-writing existing file fstime.c' fi sed 's/^X//' > fstime.c <<'End-of-File-Grunt' X/* X * $Header: fstime.c,v 3.4 87/06/22 14:23:05 kjmcdonell Beta $ X */ X X#include <stdio.h> X#include <sys/types.h> X#ifdef SysV X#include <sys/times.h> X#include <sys/param.h> X#ifdef interdata X#define HZ tbuffer.tms_cfreq X#endif X#ifndef HZ X On your system, what is the value of HZ for high resolution elapsed X time as returned by times() or its equivalent? X#endif X#endif X#ifdef BSD4v1 X#include <sys/timeb.h> X#endif X#ifdef BSD4v2 X#include <sys/time.h> X#endif X#define NKBYTE 20 Xchar buf[BUFSIZ]; X Xmain(argc, argv) Xchar **argv; X{ X int n = NKBYTE; X int nblock; X int f; X int g; X int i; X int xfer, t; X long then; X#ifdef BSD4v1 X struct timeb tbuf; X int msec; X#endif X#ifdef BSD4v2 X struct timeval tval; X struct timezone tzone; X long usec; X#endif X#ifdef SysV X struct tms tbuffer; X#endif X X if (argc > 1) X n = atoi(argv[1]); X#if debug X printf("File size: %d Kbytes\n", n); X#endif X nblock = (n * 1024) / BUFSIZ; X X if (argc == 3 && chdir(argv[2]) != -1) { X#if debug X printf("Create files in directory: %s\n", argv[2]); X#endif X } X close(creat("dummy0", 0600)); X close(creat("dummy1", 0600)); X f = open("dummy0", 2); X g = open("dummy1", 2); X unlink("dummy0"); X unlink("dummy1"); X for (i = 0; i < sizeof(buf); i++) X buf[i] = i & 0177; X X#ifdef SysV X then = times(&tbuffer); X#else X#ifdef BSD4v1 X ftime(&tbuf); X then = tbuf.time; X msec = tbuf.millitm; X#else X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X then = tval.tv_sec; X usec = tval.tv_usec; X#else X What sort of Unix system if this? X#endif X#endif X#endif X for (i = 0; i < nblock; i++) { X if (write(f, buf, sizeof(buf)) <= 0) X perror("fstime: write"); X } X#ifdef SysV X t = 1000*(times(&tbuffer) - then)/HZ; X#endif X#ifdef BSD4v1 X ftime(&tbuf); X t = (tbuf.time - then)*1000 + tbuf.millitm - msec; X#endif X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X t = (tval.tv_sec - then)*1000 + (tval.tv_usec - usec)/1000; X#endif X#if debug X printf("Effective write rate: "); X#endif X if (t > 0) { X xfer = nblock * sizeof(buf) * 1000 / t; X#if debug X printf("%d bytes/sec\n", xfer); X#endif X } X#if debug X else X printf(" -- too quick to time!\n"); X#endif X#if awk X fprintf(stderr, "%.2f", t > 0 ? (float)xfer/1024 : 0); X#endif X X sync(); X sleep(5); X sync(); X lseek(f, 0L, 0); X#ifdef SysV X then = times(&tbuffer); X#endif X#ifdef BSD4v1 X times(&tbuf); X then = tbuf.time; X msec = tbuf.millitm; X#endif X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X then = tval.tv_sec; X usec = tval.tv_usec; X#endif X for (i = 0; i < nblock; i++) { X if (read(f, buf, sizeof(buf)) <= 0) X perror("fstime: read"); X } X#ifdef SysV X t = 1000*(times(&tbuffer) - then)/HZ; X#endif X#ifdef BSD4v1 X ftime(&tbuf); X t = (tbuf.time - then)*1000 + tbuf.millitm - msec; X#endif X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X t = (tval.tv_sec - then)*1000 + (tval.tv_usec - usec)/1000; X#endif X#if debug X printf("Effective read rate: "); X#endif X if (t > 0) { X xfer = nblock * sizeof(buf) * 1000 / t; X#if debug X printf("%d bytes/sec\n", xfer); X#endif X } X#if debug X else X printf(" -- too quick to time!\n"); X#endif X#if awk X fprintf(stderr, " %.2f", t > 0 ? (float)xfer/1024 : 0); X#endif X X sync(); X sleep(5); X sync(); X lseek(f, 0L, 0); X#ifdef SysV X then = times(&tbuffer); X#endif X#ifdef BSD4v1 X times(&tbuf); X then = tbuf.time; X msec = tbuf.millitm; X#endif X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X then = tval.tv_sec; X usec = tval.tv_usec; X#endif X for (i = 0; i < nblock; i++) { X if (read(f, buf, sizeof(buf)) <= 0) X perror("fstime: read in copy"); X if (write(g, buf, sizeof(buf)) <= 0) X perror("fstime: write in copy"); X } X#ifdef SysV X t = 1000*(times(&tbuffer) - then)/HZ; X#endif X#ifdef BSD4v1 X ftime(&tbuf); X t = (tbuf.time - then)*1000 + tbuf.millitm - msec; X#endif X#ifdef BSD4v2 X gettimeofday(&tval, &tzone); X t = (tval.tv_sec - then)*1000 + (tval.tv_usec - usec)/1000; X#endif X#if debug X printf("Effective copy rate: "); X#endif X if (t > 0) { X xfer = nblock * sizeof(buf) * 1000 / t; X#if debug X printf("%d bytes/sec\n", xfer); X#endif X } X#if debug X else X printf(" -- too quick to time!\n"); X#endif X#if awk X fprintf(stderr, " %.2f\n", t > 0 ? (float)xfer/1024 : 0); X#endif X exit(0); X} End-of-File-Grunt if test 4352 -ne `cat 'fstime.c' | wc -c` then echo 'shar: transmission error (expected 4352 characters)' fi echo 'x - getwork.c' if test -f 'getwork.c' then echo 'shar: over-writing existing file getwork.c' fi sed 's/^X//' > getwork.c <<'End-of-File-Grunt' X#include "makework.h" X#ifndef lint Xstatic char RCSid[] = "$Header: getwork.c,v 1.3 87/06/23 17:01:47 kjmcdonell Beta $"; X#endif X X/* X * Build data structures (work[0] ... work[want-1]) for the next set X * of job streams. X */ X Xstream work[MAXSTREAM]; X Xtypedef struct st_cmd { X char *name; /* pathname of the command */ X char **argv; /* command argv[] vector */ X struct st_cmd *next; X} cmd; X Xtypedef struct st_scr { X char *name; /* name of the script file */ X char *buf; /* the text of the script */ X int blen; /* size of buf[] */ X struct st_scr *next; X} scr; X Xstatic cmd *cmd_head = (cmd *)0, *cmdp; Xstatic scr *scr_head = (scr *)0, *scrp; X Xgetwork(want) Xint want; X{ X int i; X int f; X int ac; X char *lp; X char *q; X stream *w; X char line[512]; X char c; X int nwork = 0; X int new; X char *malloc(), *realloc(); X X while (nwork < want) { X if (gets(line) == NULL) { X fprintf(stderr, "Insufficient job streams in the workload file\n"); X fflush(stderr); X exit(4); X } X if (nwork >= MAXSTREAM) { X fprintf(stderr, "makework: internal snark -- code is broken!\n"); X fflush(stderr); X exit(4); X } X w = &work[nwork]; X q = lp = line; X i = 1; X while (*q && *q != ' ') { X i++; X q++; X } X *q = '\0'; X if (w->home != (char *)0) X free(w->home); X w->home = (char *)malloc(strlen(lp)+1); X strcpy(w->home, lp); X X lp = ++q; X i = 1; X while (*q && *q != ' ') { X i++; X q++; X } X *q++ = '\0'; X new = 0; X for (cmdp = cmd_head; cmdp != (cmd *)0; cmdp = cmdp->next) { X if (strcmp(cmdp->name, lp) == 0) X break; X } X if (cmdp == (cmd *)0) { X cmdp = (cmd *)malloc(sizeof(*cmdp)); X cmdp->next = cmd_head; X cmd_head = cmdp; X cmdp->name = (char *)malloc(strlen(lp)+1); X strcpy(cmdp->name, lp); X new = 1; X lp = q; X /* start to build arg list */ X ac = 2; X cmdp->argv = (char **)malloc(2*sizeof(char *)); X q = cmdp->name; X while (*q) q++; X q--; X while (q >= cmdp->name) { X if (*q == '/') { X q++; X break; X } X q--; X } X cmdp->argv[0] = q; X } X else X lp = q; X w->cmd = cmdp->name; X w->av = cmdp->argv; X w->blen = 0; X w->buf = ""; X w->tty = ""; X X while (*lp) { X if (*lp == ' ') { X /* space */ X lp++; X continue; X } X else if (*lp == '>') { X /* standard output for this job */ X q = ++lp; X while (*q && *q != ' ') X q++; X c = *q; X *q = '\0'; X if (w->tty != (char *)0) X free(w->tty); X w->tty = (char *)malloc(strlen(lp)+1); X strcpy(w->tty, lp); X *q = c; X lp = q; X } X else if (*lp == '<') { X /* standard input for this job */ X q = ++lp; X while (*q && *q != ' ') q++; X c = *q; X *q = '\0'; X for (scrp = scr_head; scrp != (scr *)0; scrp = scrp->next) { X if (strcmp(scrp->name, lp) == 0) X break; X } X if (scrp == (scr *)0) { X scrp = (scr *)malloc(sizeof(*scrp)); X scrp->next = scr_head; X scr_head = scrp; X scrp->name = (char *)malloc(strlen(lp)+1); X strcpy(scrp->name, lp); X if ((f = open(lp, 0)) == -1) { X fprintf(stderr, "cannot open input file \"%s\"\n", lp); X fflush(stderr); X exit(4); X } X /* gobble input */ X scrp->buf = (char *)malloc(512); X while ((i = read(f, &scrp->buf[scrp->blen], 512)) > 0) { X scrp->blen += i; X scrp->buf = (char *)realloc(scrp->buf, scrp->blen+512); X } X scrp->buf = (char *)realloc(scrp->buf, scrp->blen); X close(f); X } X w->buf = scrp->buf; X w->blen = scrp->blen; X *q = c; X lp = q; X } X else { X /* a command option */ X q = lp; X i = 1; X while (*q && *q != ' ') { X q++; X i++; X } X if (new) { X ac++; X cmdp->argv = (char **)realloc(cmdp->argv, ac*sizeof(char *)); X cmdp->argv[ac-2] = (char *)malloc(i); X strncpy(cmdp->argv[ac-2], lp, i-1); X cmdp->argv[ac-2][i-1] = '\0'; X } X lp = q; X } X } X if (new) X cmdp->argv[ac-1] = (char *)0; X w->av = cmdp->argv; X nwork++; X } X} End-of-File-Grunt if test 3926 -ne `cat 'getwork.c' | wc -c` then echo 'shar: transmission error (expected 39 stds to t989d */ X