minix/minix/benchmarks/unixbench-5.1.2/src/dummy.c

320 lines
7.4 KiB
C

/*******************************************************************************
* The BYTE UNIX Benchmarks - Release 3
* Module: dummy.c SID: 3.3 5/15/91 19:30:19
*
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* Ben Smith, Rick Grehan or Tom Yager
* ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
*
*******************************************************************************
* Modification Log:
* 10/22/97 - code cleanup to remove ANSI C compiler warnings
* Andy Kahn <kahn@zk3.dec.com>
*
******************************************************************************/
/*
* Hacked up C program for use in the standard shell.? scripts of
* the multiuser test. This is based upon makework.c, and is typically
* edited using edscript.2 before compilation.
*
* $Header: dummy.c,v 3.4 87/06/23 15:54:53 kjmcdonell Beta $
*/
char SCCSid[] = "@(#) @(#)dummy.c:3.3 -- 5/15/91 19:30:19";
#include <stdio.h>
#include <signal.h>
#define DEF_RATE 5.0
#define GRANULE 5
#define CHUNK 60
#define MAXCHILD 12
#define MAXWORK 10
float thres;
float est_rate = DEF_RATE;
int nusers; /* number of concurrent users to be simulated by
* this process */
int firstuser; /* ordinal identification of first user for this
* process */
int nwork = 0; /* number of job streams */
int exit_status = 0; /* returned to parent */
int sigpipe; /* pipe write error flag */
struct st_work {
char *cmd; /* name of command to run */
char **av; /* arguments to command */
char *input; /* standard input buffer */
int inpsize; /* size of standard input buffer */
} work[MAXWORK];
struct {
int xmit; /* # characters sent */
char *bp; /* std input buffer pointer */
int blen; /* std input buffer length */
int fd; /* stdin to command */
int pid; /* child PID */
char *line; /* start of input line */
int firstjob; /* inital piece of work */
int thisjob; /* current piece of work */
} child[MAXCHILD], *cp;
main(argc, argv)
int argc;
char *argv[];
{
int i;
int l;
int fcopy = 0; /* fd for copy output */
int master = 1; /* the REAL master, == 0 for clones */
int nchild; /* no. of children for a clone to run */
int done; /* count of children finished */
int output; /* aggregate output char count for all
children */
int c;
int thiswork = 0; /* next job stream to allocate */
int nch; /* # characters to write */
int written; /* # characters actully written */
char logname[15]; /* name of the log file(s) */
void onalarm(void);
void pipeerr(void);
void wrapup(void);
void grunt(void);
char *malloc();
int pvec[2]; /* for pipes */
char *p;
char *prog; /* my name */
#if ! debug
freopen("masterlog.00", "a", stderr);
#endif
fprintf(stderr, "*** New Run *** ");
prog = argv[0];
while (argc > 1 && argv[1][0] == '-') {
p = &argv[1][1];
argc--;
argv++;
while (*p) {
switch (*p) {
case 'r':
/* code DELETED here */
argc--;
argv++;
break;
case 'c':
/* code DELETED here */
lseek(fcopy, 0L, 2); /* append at end of file */
break;
default:
fprintf(stderr, "%s: bad flag '%c'\n", prog, *p);
exit(4);
}
p++;
}
}
if (argc < 2) {
fprintf(stderr, "%s: missing nusers\n", prog);
exit(4);
}
nusers = atoi(argv[1]);
if (nusers < 1) {
fprintf(stderr, "%s: impossible nusers (%d<-%s)\n", prog, nusers, argv[1]);
exit(4);
}
fprintf(stderr, "%d Users\n", nusers);
argc--;
argv++;
/* build job streams */
getwork();
#if debug
dumpwork();
#endif
/* clone copies of myself to run up to MAXCHILD jobs each */
firstuser = MAXCHILD;
fprintf(stderr, "master pid %d\n", getpid());
fflush(stderr);
while (nusers > MAXCHILD) {
fflush(stderr);
if (nusers >= 2*MAXCHILD)
/* the next clone must run MAXCHILD jobs */
nchild = MAXCHILD;
else
/* the next clone must run the leftover jobs */
nchild = nusers - MAXCHILD;
if ((l = fork()) == -1) {
/* fork failed */
fatal("** clone fork failed **\n");
goto bepatient;
} else if (l > 0) {
fprintf(stderr, "master clone pid %d\n", l);
/* I am the master with nchild fewer jobs to run */
nusers -= nchild;
firstuser += MAXCHILD;
continue;
} else {
/* I am a clone, run MAXCHILD jobs */
#if ! debug
sprintf(logname, "masterlog.%02d", firstuser/MAXCHILD);
freopen(logname, "w", stderr);
#endif
master = 0;
nusers = nchild;
break;
}
}
if (master)
firstuser = 0;
close(0);
/* code DELETED here */
fflush(stderr);
srand(time(0));
thres = 0;
done = output = 0;
for (i = 0; i < nusers; i++) {
if (child[i].blen == 0)
done++;
else
thres += est_rate * GRANULE;
}
est_rate = thres;
signal(SIGALRM, onalarm);
signal(SIGPIPE, pipeerr);
alarm(GRANULE);
while (done < nusers) {
for (i = 0; i < nusers; i++) {
cp = &child[i];
if (cp->xmit >= cp->blen) continue;
l = rand() % CHUNK + 1; /* 1-CHUNK chars */
if (l == 0) continue;
if (cp->xmit + l > cp->blen)
l = cp->blen - cp->xmit;
p = cp->bp;
cp->bp += l;
cp->xmit += l;
#if debug
fprintf(stderr, "child %d, %d processed, %d to go\n", i, cp->xmit, cp->blen - cp->xmit);
#endif
while (p < cp->bp) {
if (*p == '\n' || (p == &cp->bp[-1] && cp->xmit >= cp->blen)) {
/* write it out */
nch = p - cp->line + 1;
if ((written = write(cp->fd, cp->line, nch)) != nch) {
/* code DELETED here */
}
if (fcopy)
write(fcopy, cp->line, p - cp->line + 1);
#if debug
fprintf(stderr, "child %d gets \"", i);
{
char *q = cp->line;
while (q <= p) {
if (*q >= ' ' && *q <= '~')
fputc(*q, stderr);
else
fprintf(stderr, "\\%03o", *q);
q++;
}
}
fputc('"', stderr);
#endif
cp->line = &p[1];
}
p++;
}
if (cp->xmit >= cp->blen) {
done++;
close(cp->fd);
#if debug
fprintf(stderr, "child %d, close std input\n", i);
#endif
}
output += l;
}
while (output > thres) {
pause();
#if debug
fprintf(stderr, "after pause: output, thres, done %d %.2f %d\n", output, thres, done);
#endif
}
}
bepatient:
alarm(0);
/****
* If everything is going OK, we should simply be able to keep
* looping unitil 'wait' fails, however some descendent process may
* be in a state from which it can never exit, and so a timeout
* is used.
* 5 minutes should be ample, since the time to run all jobs is of
* the order of 5-10 minutes, however some machines are painfully slow,
* so the timeout has been set at 20 minutes (1200 seconds).
****/
/* code DELETED here */
}
onalarm()
{
thres += est_rate;
signal(SIGALRM, onalarm);
alarm(GRANULE);
}
grunt()
{
/* timeout after label "bepatient" in main */
exit_status = 4;
wrapup();
}
pipeerr()
{
sigpipe++;
}
wrapup()
{
/* DUMMY, real code dropped */
}
getwork()
{
/* DUMMY, real code dropped */
gets();
strncpy();
malloc(); realloc();
open(); close();
}
fatal(s)
char *s;
{
int i;
fprintf(stderr, s);
fflush(stderr);
perror("Reason?");
for (i = 0; i < nusers; i++) {
if (child[i].pid > 0 && kill(child[i].pid, SIGKILL) != -1)
fprintf(stderr, "pid %d killed off\n", child[i].pid);
}
fflush(stderr);
exit_status = 4;
return;
}