1
0
Files
2022-09-29 17:59:04 +03:00

261 lines
5.9 KiB
C

/**************************************************************************
* *
* Copyright (C) 1990-1995 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.11 $"
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <getopt.h>
#include <ulocks.h>
#include <errno.h>
#include <malloc.h>
#include <wait.h>
#include "stress.h"
extern void dumpmi(struct mallinfo *mi);
char *Cmd;
/*
* test lock allocation to the limit
* 1) check that can alloc up to max #, use them and realloc them
* 2) check that recovery after failure (not freeing) doesn't cause
* problems for next invocation
* 3) show that sproc guys can alloc new pages of locks
*/
#define OVERHEAD 7
usptr_t *arena;
int nlocks = 4096;
int asize = (1024*1024);
int quit;
int childonly = 0;
int verbose = 0;
char *filename;
struct mallinfo mi;
void
TestLocks(int nofree, int expect, pid_t pid)
{
int i;
ulock_t *lock;
if(!(lock = (ulock_t *)malloc(nlocks * sizeof(ulock_t)))) {
errprintf(3, "malloc of locks array size=%d fails",
nlocks * sizeof(ulock_t));
return;
}
for(i = 0; i < nlocks; i++) {
lock[i] = usnewlock(arena);
if (lock[i] == NULL) {
if (verbose)
printf("alloc:%d:cannot alloc %dth lock:%s\n",
pid, i, strerror(oserror()));
break;
}
if (verbose && (i % 100) == 0)
printf("alloc:%d:Testing lock %3d, addr = 0%x\n",
pid, i, lock[i]);
ussetlock(lock[i]);
usunsetlock(lock[i]);
}
/* overhead differs between software/hardware locks
* just check to be sure got at least expected #
*/
if (i >= expect) {
if (verbose)
printf("alloc:%d:Lock test passed. expected %d & got %d locks\n",
pid, expect, i);
} else
errprintf(1, "expected %d and got %d locks", expect, i);
/* NOTREACHED */
if (!nofree) {
if (verbose)
printf("alloc:%d:freeing %d locks\n", get_pid(), i);
while (--i >= 0)
usfreelock(lock[i], arena);
}
}
void
Child(int nlocks)
{
slaveexinit();
if (verbose)
printf("alloc:%d:child alloc and %s\n",
get_pid(), quit ? "leave" : "dealloc");
TestLocks(quit, nlocks, get_pid());
if (verbose)
printf("alloc:%d:child is done\n", get_pid());
}
int
main(int argc, char **argv)
{
int c, status;
pid_t pid;
Cmd = errinit(argv[0]);
while((c = getopt(argc, argv, "m:dvn:c")) != EOF)
switch (c) {
case 'd':
usconfig(CONF_LOCKTYPE, US_DEBUG);
break;
case 'n':
nlocks = atoi(optarg);
break;
case 'c':
childonly++;
break;
case 'v':
verbose++;
break;
case 'm':
asize = atoi(optarg) * 1024;
break;
default:
fprintf(stderr, "Usage:alloc [-v][-c][-d][-n #][-m size (kb)]\n");
exit(-1);
}
usconfig(CONF_INITSIZE, asize);
filename = tempnam(NULL, "alloc");
if ((arena = usinit(filename)) == NULL) {
errprintf(1, "usinit");
/* NOTREACHED */
}
quit = 0; /* dealloc locks */
if (!childonly) {
if (verbose)
printf("alloc:%d:parent alloc and dealloc\n", get_pid());
TestLocks(quit, nlocks - OVERHEAD, get_pid());
}
mi = usmallinfo(arena);
dumpmi(&mi);
/*
* in case parent decides to exit - this makes sure that all
* kids will be killed
*/
parentexinit(0);
pid = sproc((void(*)(void *))Child, PR_SALL, nlocks - OVERHEAD);
if (pid < 0) {
unlink(filename);
if (errno != EAGAIN) {
errprintf(1, "sproc failed");
/* NOTREACHED */
}
printf("%s:can't sproc:%s\n", Cmd, strerror(errno));
exit(0);
}
/* wait for child */
for (;;) {
pid = wait(&status);
if (pid < 0 && errno == ECHILD)
break;
else if ((pid >= 0) && WIFSIGNALED(status)) {
/*
* if anyone dies abnormally - get out
* But don't abort - the process that got the signal
* hopefully aborted - that core dump is more
* interesting
*/
errprintf(2, "proc %d died of signal %d\n",
pid, WTERMSIG(status));
unlink(filename);
if (!WCOREDUMP(status))
abort();
exit(1);
}
}
mi = usmallinfo(arena);
dumpmi(&mi);
quit = 1;
if (!childonly) {
if (verbose)
printf("alloc:%d:parent alloc and leave\n", get_pid());
TestLocks(quit, nlocks - OVERHEAD, get_pid());
}
mi = usmallinfo(arena);
dumpmi(&mi);
pid = sproc((void(*)(void *))Child, PR_SALL,
childonly ? nlocks - OVERHEAD : 0);
if (pid < 0) {
unlink(filename);
if (errno != EAGAIN) {
errprintf(1, "sproc failed");
/* NOTREACHED */
}
printf("%s:can't sproc:%s\n", Cmd, strerror(errno));
exit(0);
}
/* wait for child */
for (;;) {
pid = wait(&status);
if (pid < 0 && errno == ECHILD)
break;
else if ((pid >= 0) && WIFSIGNALED(status)) {
/*
* if anyone dies abnormally - get out
* But don't abort - the process that got the signal
* hopefully aborted - that core dump is more
* interesting
*/
errprintf(2, "proc %d died of signal %d\n",
pid, WTERMSIG(status));
unlink(filename);
if (!WCOREDUMP(status))
abort();
exit(1);
}
}
mi = usmallinfo(arena);
dumpmi(&mi);
printf("%s:%d:PASSED\n", Cmd, getpid());
unlink(filename);
return 0;
}
void
dumpmi(struct mallinfo *mi)
{
size_t size;
if (verbose) {
printf("Mallinfo:arena:%d ordblks:%d smblks:%d hblkhd:%d\n",
mi->arena, mi->ordblks, mi->smblks, mi->hblkhd);
printf("\thblks:%d usmblks:%d fsmblks:%d uordblks:%d\n",
mi->hblks, mi->usmblks, mi->fsmblks, mi->uordblks);
printf("\tfordblks:%d keepcost:%d\n",
mi->fordblks, mi->keepcost);
}
size = mi->hblkhd + mi->usmblks + mi->fsmblks + mi->uordblks +
mi->fordblks;
if (mi->arena != size)
errprintf(ERR_EXIT, "size %d != arena %d\n", size, mi->arena);
}