1
0
Files
irix-657m-src/irix/cmd/stress/Mmap/aglock.c
2022-09-29 17:59:04 +03:00

384 lines
7.3 KiB
C

/**************************************************************************
* *
* Copyright (C) 1986, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#ident "$Revision: 1.4 $ $Author: yohn $"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <getopt.h>
#include <ulocks.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <signal.h>
#include "stress.h"
usptr_t *handle;
#define FSZ 0x20000
#define FSS 0x02000
char *Cmd;
char *semfile;
char *agfile;
usema_t *truncsema;
pid_t checkerid, truncid;
int agfd, agrwfd;
int nreps = 25;
caddr_t vaddr;
static char c = 'a';
pid_t ppid;
int keepgoing;
int nblockproc;
int verbose;
int off;
int pgsize;
void catchit(int, int, struct sigcontext *);
void storer(int, int);
void checker(void *), trunc(void *);
void loader(off_t start, off_t len, int id);
void reader(off_t start, off_t len, int id);
int
main(int argc, char **argv)
{
void (*routine)(off_t, off_t, int);
int c, i, errflg = 0;
Cmd = errinit(argv[0]);
ppid = getpid();
while ((c = getopt(argc, argv, "vn:")) != -1)
switch (c) {
case 'v':
verbose++;
break;
case 'n':
nreps = atoi(optarg);
break;
case '?':
errflg++;
break;
}
if (errflg) {
fprintf(stderr, "Usage: aglock [-v][-n loops]\n");
exit(1);
}
semfile = tempnam(NULL, "aglock");
usconfig(CONF_ARENATYPE, US_SHAREDONLY);
handle = usinit(semfile);
if (handle == (usptr_t *)0)
errprintf(ERR_ERRNO_EXIT, "usinit of %s failed", semfile);
truncsema = usnewsema(handle, 1);
if (truncsema == (usema_t *)0)
errprintf(ERR_ERRNO_EXIT, "usnewsema failed");
agfile = tempnam(NULL, "aglock");
agfd = open(agfile, O_RDWR | O_CREAT, 0777);
if (agfd < 0)
errprintf(ERR_ERRNO_EXIT, "create %s", agfile);
agrwfd = open(agfile, O_RDWR);
if (agrwfd < 0) {
errprintf(ERR_ERRNO_RET, "open %s for write failed", agfile);
goto bad;
}
srand(time((time_t *)0));
pgsize = getpagesize();
keepgoing = 1;
printf("%s: doing %d reps\n", argv[0], nreps);
if (argc <= 2) {
off = (rand() % FSS) & ~(pgsize -1);
vaddr = mmap(0, FSZ, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_AUTOGROW, agrwfd, off);
if (vaddr == (caddr_t) -1L) {
errprintf(ERR_ERRNO_RET, "mmap tfile");
goto bad;
} else if (verbose)
printf("aglock:mapped at 0x%x from 0x%x\n", vaddr, off);
routine = loader;
} else
routine = reader;
checkerid = sproc(checker, PR_SALL, 0);
if (checkerid < 0) {
perror("aglock:can't sproc");
unlink(agfile);
exit(1);
}
nblockproc++;
truncid = sproc(trunc, PR_SALL, 0);
if (truncid < 0) {
perror("aglock:can't sproc");
kill(checkerid, SIGKILL);
unlink(agfile);
exit(1);
}
nblockproc++;
for (i = 0; i < nreps; i++) {
off_t start = rand() % FSZ;
off_t len = rand() % (FSZ - start);
(*routine)(start, len, i);
sginap(20);
}
keepgoing = 0;
while (nblockproc--) {
blockproc(ppid);
}
usfreesema(truncsema, handle);
unlink(agfile);
exit(0);
bad:
unlink(agfile);
abort();
}
char *gs;
off_t glen;
char bytebucket;
void
loader(off_t start, off_t len, int id)
{
volatile char *bb;
off_t pinstart, pinlen;
bb = &bytebucket;
if (verbose)
printf("aglock:loading(%d) 0x%x bytes from %x for %x...",
id, start + off, len);
fflush(stdout);
gs = vaddr + start;
if (signal(SIGSEGV, storer) == SIG_ERR) {
keepgoing = 0;
blockproc(ppid);
blockproc(ppid);
usfreesema(truncsema, handle);
exit(1);
}
fflush(stdout);
for (glen = len; glen > 0; glen--) {
*bb = *gs;
gs++;
}
pinstart = rand() % FSZ;
if (pinstart >= start + len)
pinstart = start + len / 2;
pinlen = rand() % (FSZ - pinstart);
while (mpin(vaddr + pinstart, pinlen)) {
pinlen -= pgsize;
if (pinlen <= 0)
break;
}
if (verbose)
printf("aglock:pinned @%x for %x...", pinstart, pinlen);
fflush(stdout);
}
void
storer(int sig, int code)
{
int j;
char *s = gs;
/* re-enable signal handling here to catch if storing fails */
signal(SIGSEGV, catchit);
if (code == EBUSY) {
if (verbose)
printf("unlocking pages (storer)...");
fflush(stdout);
munpin(vaddr, FSZ);
signal(SIGSEGV, storer);
return;
}
if (verbose)
printf("aglock:storing 0x%x bytes of %c...(got error %d) ",
glen, c, code);
fflush(stdout);
for (j = 0; j < glen; j++)
*s++ = c;
if (c == 'z')
c = 'a';
else
c++;
if (signal(SIGSEGV, storer) == SIG_ERR) {
keepgoing = 0;
blockproc(ppid);
blockproc(ppid);
usfreesema(truncsema, handle);
exit(1);
}
}
void
reader(off_t start, off_t len, int id)
{
int bytesread;
char buf[FSZ];
printf("aglock:reading from %x for %x...", start, len);
fflush(stdout);
if (lseek(agrwfd, start, 0) < 0) {
perror("aglock:lseek");
exit(1);
}
bytesread = read(agrwfd, buf, len);
if (bytesread < len) {
register int j;
len = len - bytesread;
printf("aglock:writing 0x%x bytes of %c...", len, c);
fflush(stdout);
for (j = 0; j < len; j++)
buf[j] = c;
if (write(agrwfd, buf, len) != len) {
perror("aglock:reader write");
exit(1);
}
if (c == 'z')
c = 'a';
else
c++;
}
}
/*
* signal handler when parent should NOT get a signal - implies
* file system full or something
*/
void
catchit(int sig, int code, struct sigcontext *scp)
{
if (code == EBUSY) {
signal(SIGSEGV, catchit);
if (verbose)
printf("unlocking pages (catchit)...");
fflush(stdout);
munpin(vaddr, FSZ);
return;
}
errprintf(ERR_RET, "caught unexpected signal %d - code %d:%s",
sig, code, strerror(code));
keepgoing = 0;
blockproc(ppid);
blockproc(ppid);
usfreesema(truncsema, handle);
abort();
}
/*
* one sproc slave does random truncates
*/
void
trunc(void *arg)
{
do {
int tval;
tval = rand() % FSZ;
if (verbose)
printf("aglock:truncating to 0x%x...", tval);
fflush(stdout);
uspsema(truncsema);
if (ftruncate(agfd, tval)) {
usvsema(truncsema);
errprintf(ERR_ERRNO_RET, "ftruncate");
unblockproc(ppid);
abort();
}
usvsema(truncsema);
sginap(40);
} while (keepgoing);
unblockproc(ppid);
}
/*
* one sproc guy does checks
*/
void
checker(void *arg)
{
struct stat statb;
register int fd, size, j;
char buf[FSZ];
fd = open(agfile, O_RDONLY);
if (fd < 0) {
errprintf(ERR_ERRNO_RET, "open");
unblockproc(ppid);
abort();
}
do {
sleep(1);
uspsema(truncsema);
if (stat(agfile, &statb) < 0) {
usvsema(truncsema);
errprintf(ERR_ERRNO_RET, "stat");
unblockproc(ppid);
abort();
}
if (verbose)
printf("aglock:checking 0x%x...", statb.st_size);
fflush(stdout);
lseek(fd, 0, 0);
size = read(fd, buf, statb.st_size);
if (size != statb.st_size) {
errprintf(ERR_RET, "got 0x%x bytes, not 0x%x",
size, statb.st_size);
abort();
}
usvsema(truncsema);
for (j = 0; j < size; j++) {
if (buf[j] != 0 && (buf[j] < 'a' || buf[j] > 'z')) {
errprintf(ERR_RET,
"checker: got %d: byte 0x%x of 0x%x!",
buf[j], j, size);
unblockproc(ppid);
abort();
}
}
} while (keepgoing);
unblockproc(ppid);
}