319 lines
7.4 KiB
C
319 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;
|
|
}
|