761 lines
17 KiB
C
761 lines
17 KiB
C
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1990, 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.12 $"
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdarg.h>
|
|
#include <getopt.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <bstring.h>
|
|
#include <signal.h>
|
|
#include <ulocks.h>
|
|
#include <errno.h>
|
|
#include <pwd.h>
|
|
#include <wait.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/sysmacros.h>
|
|
#include "stress.h"
|
|
|
|
/*
|
|
* test pollable semaphore allocation
|
|
* 1) alloc, use, free, re-alloc
|
|
* 2) sproc guys can alloc/free
|
|
* 3) unrelated procs can alloc/free
|
|
* 4) other user-ids can alloc
|
|
*/
|
|
#define MAXSEMAS FD_SETSIZE
|
|
#define DEFARENASIZE 128 /* 128kb */
|
|
#define DEFUSERS 4
|
|
#define DEFACQUIRES 4
|
|
#define DEFLOOPS 2
|
|
#define DEFGUEST "guest"
|
|
|
|
char *Cmd;
|
|
char *afile;
|
|
/*
|
|
* per sema info
|
|
*/
|
|
struct ss {
|
|
usema_t *sp;
|
|
int *fd;
|
|
dev_t dev;
|
|
};
|
|
|
|
/*
|
|
* all shared info goes here - the address of this struct is passed
|
|
* via usgetinfo
|
|
*/
|
|
struct sinfo {
|
|
struct ss *s;
|
|
pid_t *pids;
|
|
int nusers;
|
|
int nacquires;
|
|
int nsemas;
|
|
long myturn;
|
|
char afile[512];
|
|
int unrel;
|
|
barrier_t *b;
|
|
};
|
|
|
|
void simple1(void *);
|
|
void killall(usptr_t *);
|
|
int allocsemas(usptr_t *, struct ss *, int, int);
|
|
void deallocsemas(usptr_t *, struct ss *);
|
|
int opensemas(usptr_t *, struct ss *, int);
|
|
void closesemas(usptr_t *, struct ss *);
|
|
void ignunlink(char *f);
|
|
|
|
int debug = 0;
|
|
int verbose = 0;
|
|
int maxsemas = MAXSEMAS;
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int c;
|
|
int err = 0;
|
|
int i, j;
|
|
int nloops = DEFLOOPS;
|
|
int arenasize = DEFARENASIZE;
|
|
int nusers = DEFUSERS;
|
|
int nacquires = DEFACQUIRES;
|
|
int mpid;
|
|
int idfield;
|
|
long myturn;
|
|
char *nargs[32];
|
|
register struct sinfo *sd;
|
|
register usptr_t *handle;
|
|
register struct ss *s;
|
|
register pid_t *pids;
|
|
struct passwd *pw;
|
|
int badperm = 0;
|
|
int nosproctest = 0;
|
|
int noforktest = 0;
|
|
char *Argv0;
|
|
|
|
Cmd = errinit(argv[0]);
|
|
Argv0 = argv[0];
|
|
while ((c = getopt(argc, argv, "pA:E:l:vdn:u:m:SFs:")) != EOF) {
|
|
switch (c) {
|
|
case 'F':
|
|
noforktest++;
|
|
break;
|
|
case 'S':
|
|
nosproctest++;
|
|
break;
|
|
case 'v':
|
|
verbose++;
|
|
break;
|
|
case 'd':
|
|
debug++;
|
|
break;
|
|
case 's':
|
|
maxsemas = atoi(optarg);
|
|
break;
|
|
case 'u':
|
|
nusers = atoi(optarg);
|
|
break;
|
|
case 'm':
|
|
arenasize = atoi(optarg);
|
|
break;
|
|
case 'l':
|
|
nloops = atoi(optarg);
|
|
break;
|
|
case 'n':
|
|
nacquires = atoi(optarg);
|
|
break;
|
|
case 'A': /* internal execed option to pass afile */
|
|
afile = optarg;
|
|
break;
|
|
case 'E': /* internal execed option to pass tid */
|
|
myturn = atol(optarg);
|
|
simple1((void *)myturn);
|
|
exit(0);
|
|
case 'p':
|
|
/* run with incorrect permissions on arena */
|
|
badperm++;
|
|
break;
|
|
case '?':
|
|
err++;
|
|
break;
|
|
}
|
|
}
|
|
mpid = get_pid();
|
|
if (err) {
|
|
fprintf(stderr, "Usage: %s [-pvFS][-d][-u users][-n acquires][-m arena size (inKb)][-l loops][-s nsemas]\n", Cmd);
|
|
fprintf(stderr, "\t-S do not run sproc test\n");
|
|
fprintf(stderr, "\t-F do not run fork test\n");
|
|
fprintf(stderr, "\t-p run with incorrect arena permissions\n");
|
|
exit(1);
|
|
}
|
|
if (debug)
|
|
usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
|
|
|
|
if (usconfig(CONF_INITUSERS, nusers) < 0)
|
|
errprintf(1, "INITUSERS");
|
|
usconfig(CONF_INITSIZE, arenasize * 1024);
|
|
|
|
if (nosproctest)
|
|
goto forktest;
|
|
|
|
printf("%s:%d: SPROC TEST:# users %d # loops %d # acquires %d nsemas %d\n",
|
|
Cmd, get_pid(), nusers, nloops, nacquires, maxsemas);
|
|
usconfig(CONF_ARENATYPE, US_SHAREDONLY);
|
|
|
|
afile = tempnam(NULL, "usemaalloc");
|
|
if ((handle = usinit(afile)) == NULL)
|
|
errprintf(1, "usinit of %s failed", afile);
|
|
|
|
s = malloc(MAXSEMAS * sizeof(*s));
|
|
pids = malloc(nusers * sizeof(pid_t));
|
|
if ((sd = usmalloc(sizeof(*sd), handle)) == NULL) {
|
|
errprintf(1, "usmalloc of shared data area failed");
|
|
/* NOTREACHED */
|
|
}
|
|
sd->s = s;
|
|
sd->pids = pids;
|
|
sd->nacquires = nacquires;
|
|
sd->nusers = nusers;
|
|
sd->unrel = 0;
|
|
if ((sd->b = new_barrier(handle)) == NULL) {
|
|
errprintf(1, "new_barrier failed");
|
|
/* NOTHREACHED */
|
|
}
|
|
usputinfo(handle, sd);
|
|
|
|
if (debug)
|
|
usconfig(CONF_HISTON, handle);
|
|
prctl(PR_SETSTACKSIZE, 64*1024);
|
|
|
|
|
|
pids[0] = mpid;
|
|
myturn = 0;
|
|
sd->myturn = myturn;
|
|
for (j = 0; j < nloops; j++) {
|
|
for (i = 1; i < nusers; i++)
|
|
pids[i] = 0;
|
|
/* start up all users */
|
|
for (i = 1; i < nusers; i++) {
|
|
if ((pids[i] = sproc(simple1, PR_SALL, i)) < 0) {
|
|
if (errno != EAGAIN) {
|
|
errprintf(3, "sproc failed i:%d", i);
|
|
killall(handle);
|
|
abort();
|
|
} else {
|
|
/* running out of procs really isn't
|
|
* an error
|
|
*/
|
|
printf("%s:can't sproc:%s\n", Cmd, strerror(errno));
|
|
killall(handle);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
simple1((void *)0);
|
|
|
|
while (wait(0) >= 0 || errno == EINTR)
|
|
;
|
|
|
|
/* all dead - now dealloc all semas */
|
|
deallocsemas(handle, s);
|
|
myturn = (myturn + 1) % nusers;
|
|
sd->myturn = myturn;
|
|
}
|
|
usdetach(handle);
|
|
|
|
forktest:
|
|
if (noforktest)
|
|
goto unreltest;
|
|
/*
|
|
* now try related via fork
|
|
*/
|
|
printf("%s:%d: FORK TEST:# users %d # loops %d # acquires %d nsemas %d\n",
|
|
Cmd, get_pid(), nusers, nloops, nacquires, maxsemas);
|
|
usconfig(CONF_ARENATYPE, US_GENERAL);
|
|
|
|
afile = tempnam(NULL, "usemaalloc");
|
|
if ((handle = usinit(afile)) == NULL) {
|
|
errprintf(1, "usinit of %s failed", afile);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
s = usmalloc(MAXSEMAS * sizeof(*s), handle);
|
|
pids = usmalloc(nusers * sizeof(pid_t), handle);
|
|
if (pids == NULL || s == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "usmalloc of semaphores failed");
|
|
/* NOTREACHED */
|
|
}
|
|
if ((sd = usmalloc(sizeof(*sd), handle)) == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "usmalloc of shared data area failed");
|
|
/* NOTREACHED */
|
|
}
|
|
sd->s = s;
|
|
sd->pids = pids;
|
|
sd->nacquires = nacquires;
|
|
sd->nusers = nusers;
|
|
sd->unrel = 1; /* unrelated procs must all init semas */
|
|
strcpy(sd->afile, afile);
|
|
if ((sd->b = new_barrier(handle)) == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "new_barrier failed");
|
|
/* NOTHREACHED */
|
|
}
|
|
usputinfo(handle, sd);
|
|
|
|
pids[0] = mpid;
|
|
myturn = 0;
|
|
sd->myturn = myturn;
|
|
for (j = 0; j < nloops; j++) {
|
|
int npid;
|
|
|
|
for (i = 1; i < nusers; i++)
|
|
pids[i] = 0;
|
|
/* start up all users */
|
|
for (i = 1; i < nusers; i++) {
|
|
if ((npid = fork()) < 0) {
|
|
if (errno != EAGAIN) {
|
|
errprintf(3, "fork failed i:%d", i);
|
|
killall(handle);
|
|
abort();
|
|
} else {
|
|
/* running out of procs really isn't
|
|
* an error
|
|
*/
|
|
printf("%s:can't fork:%s\n", Cmd, strerror(errno));
|
|
killall(handle);
|
|
exit(1);
|
|
}
|
|
} else if (npid == 0) {
|
|
/* child */
|
|
simple1((void *)(long)i);
|
|
exit(0);
|
|
}
|
|
pids[i] = npid;
|
|
}
|
|
simple1((void *)0);
|
|
|
|
while (wait(0) >= 0 || errno == EINTR)
|
|
;
|
|
|
|
/* all dead - now dealloc all semas */
|
|
deallocsemas(handle, s);
|
|
myturn = (myturn + 1) % nusers;
|
|
sd->myturn = myturn;
|
|
}
|
|
ignunlink(afile);
|
|
usdetach(handle);
|
|
|
|
unreltest:
|
|
/*
|
|
* now try unrelated and different uid
|
|
*/
|
|
if (getuid() != 0) {
|
|
printf("%s: Cannot run unrelated process test - must run as root!\n",
|
|
Cmd);
|
|
exit(0);
|
|
}
|
|
|
|
printf("%s:%d: UNRELATED TEST:# users %d # loops %d # acquires %d nsemas %d\n",
|
|
Cmd, get_pid(), nusers, nloops, nacquires, maxsemas);
|
|
usconfig(CONF_ARENATYPE, US_GENERAL);
|
|
|
|
afile = tempnam(NULL, "usemaalloc");
|
|
if ((handle = usinit(afile)) == NULL) {
|
|
errprintf(1, "usinit of %s failed", afile);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
/* set up permissions */
|
|
if (!badperm) {
|
|
if (usconfig(CONF_CHMOD, handle, 0666) != 0) {
|
|
ignunlink(afile);
|
|
errprintf(1, "CONF_CHMOD failed");
|
|
/* NOTREACHED */
|
|
}
|
|
}
|
|
|
|
s = usmalloc(MAXSEMAS * sizeof(*s), handle);
|
|
pids = usmalloc(nusers * sizeof(pid_t), handle);
|
|
if (pids == NULL || s == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "usmalloc of semaphores failed");
|
|
/* NOTREACHED */
|
|
}
|
|
if ((sd = usmalloc(sizeof(*sd), handle)) == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "usmalloc of shared data area failed");
|
|
/* NOTREACHED */
|
|
}
|
|
sd->s = s;
|
|
sd->pids = pids;
|
|
sd->nacquires = nacquires;
|
|
sd->nusers = nusers;
|
|
strcpy(sd->afile, afile);
|
|
sd->unrel = 1; /* unrelated procs must all init semas */
|
|
if ((sd->b = new_barrier(handle)) == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "new_barrier failed");
|
|
/* NOTHREACHED */
|
|
}
|
|
usputinfo(handle, sd);
|
|
|
|
/* set up args to execed children */
|
|
i = 0;
|
|
nargs[i++] = argv[0];
|
|
if (verbose)
|
|
nargs[i++] = "-v";
|
|
if (debug)
|
|
nargs[i++] = "-d";
|
|
nargs[i++] = "-A";
|
|
nargs[i++] = afile;
|
|
nargs[i++] = "-E";
|
|
idfield = i;
|
|
nargs[i++] = NULL;
|
|
nargs[i++] = NULL;
|
|
|
|
/* find new uid for children */
|
|
if ((pw = getpwnam(DEFGUEST)) == NULL) {
|
|
ignunlink(afile);
|
|
errprintf(1, "getpwnam of %s failed", DEFGUEST);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
pids[0] = mpid;
|
|
myturn = 0;
|
|
sd->myturn = myturn;
|
|
for (j = 0; j < nloops; j++) {
|
|
int npid;
|
|
|
|
for (i = 1; i < nusers; i++)
|
|
pids[i] = 0;
|
|
/* start up all users */
|
|
for (i = 1; i < nusers; i++) {
|
|
if ((npid = fork()) < 0) {
|
|
if (errno != EAGAIN) {
|
|
errprintf(3, "fork failed i:%d", i);
|
|
killall(handle);
|
|
abort();
|
|
} else {
|
|
/* running out of procs really isn't
|
|
* an error
|
|
*/
|
|
printf("%s:can't fork:%s\n", Cmd, strerror(errno));
|
|
killall(handle);
|
|
exit(1);
|
|
}
|
|
} else if (npid == 0) {
|
|
char idf[10];
|
|
|
|
/* child */
|
|
if (setgid(pw->pw_gid) != 0 ||
|
|
setuid(pw->pw_uid) != 0) {
|
|
killall(handle);
|
|
errprintf(1, "set[ug]id failed");
|
|
/* NOTREACHED */
|
|
}
|
|
sprintf(idf, "%d", i);
|
|
nargs[idfield] = idf;
|
|
execvp(Argv0, nargs);
|
|
killall(handle);
|
|
errprintf(1, "execvp of <%s> failed", Cmd);
|
|
/* NOTREACHED */
|
|
}
|
|
pids[i] = npid;
|
|
}
|
|
simple1((void *)0);
|
|
|
|
while (wait(0) >= 0 || errno == EINTR)
|
|
;
|
|
|
|
/* all dead - now dealloc all semas */
|
|
deallocsemas(handle, s);
|
|
myturn = (myturn + 1) % nusers;
|
|
sd->myturn = myturn;
|
|
}
|
|
ignunlink(afile);
|
|
printf("%s:%d:PASSED\n", Cmd, getpid());
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
killall(usptr_t *handle)
|
|
{
|
|
register int i;
|
|
struct sinfo *sd;
|
|
register int err = oserror();
|
|
|
|
sd = usgetinfo(handle);
|
|
for (i = 0; i < sd->nusers; i++)
|
|
if (sd->pids[i] != get_pid() && sd->pids[i] > 0)
|
|
kill(sd->pids[i], SIGKILL);
|
|
if (sd->afile[0])
|
|
ignunlink(sd->afile);
|
|
setoserror(err);
|
|
}
|
|
|
|
void
|
|
simple1(void *arg)
|
|
{
|
|
int whoami = (int)(long) arg;
|
|
register int i, j;
|
|
register int gotton, nwait;
|
|
fd_set lfd, tfd;
|
|
register int rv;
|
|
char buf[5120], sfd[20];
|
|
struct sinfo *sd;
|
|
register int nsemas;
|
|
register struct ss *s;
|
|
usptr_t *handle;
|
|
int fdidx;
|
|
|
|
if ((handle = usinit(afile)) == NULL)
|
|
errprintf(1, "%d slave usinit", get_pid());
|
|
sd = usgetinfo(handle);
|
|
s = sd->s;
|
|
|
|
if (sd->myturn == whoami) {
|
|
/* only alloc one set of fds for related procs */
|
|
if (!sd->unrel) {
|
|
sd->nsemas = allocsemas(handle, s, 1, 0);
|
|
fdidx = 0;
|
|
} else {
|
|
sd->nsemas = allocsemas(handle, s, sd->nusers, whoami);
|
|
fdidx = whoami;
|
|
}
|
|
/*
|
|
* make sure master has created ALL threads before unblocking
|
|
* everyone
|
|
*/
|
|
barrier(sd->b, sd->nusers);
|
|
} else {
|
|
/* wait for allocater */
|
|
barrier(sd->b, sd->nusers);
|
|
|
|
/* for unrelated procs - all must open semas */
|
|
if (sd->unrel) {
|
|
opensemas(handle, s, whoami);
|
|
fdidx = whoami;
|
|
} else {
|
|
fdidx = 0;
|
|
}
|
|
}
|
|
/* wait for everyone */
|
|
barrier(sd->b, sd->nusers);
|
|
|
|
nsemas = sd->nsemas;
|
|
nwait = 0;
|
|
for (j = 0; j < sd->nacquires; j++) {
|
|
FD_ZERO(&lfd);
|
|
gotton = 0;
|
|
for (i = 0; i < nsemas; i++) {
|
|
/*
|
|
* for unrelated procs some may not have
|
|
* enough fds to open all semas - just ignore these
|
|
*/
|
|
if (s[i].fd[fdidx] < 0) {
|
|
gotton++;
|
|
continue;
|
|
}
|
|
if ((rv = uspsema(s[i].sp)) > 0) {
|
|
/* got it */
|
|
gotton++;
|
|
sginap(1);
|
|
if (usvsema(s[i].sp) < 0) {
|
|
killall(handle);
|
|
errprintf(1, "%d usvsema failed i %d sp 0x%x",
|
|
get_pid(), i, s[i].sp);
|
|
/* NOTREACHED */
|
|
}
|
|
} else if (rv < 0) {
|
|
killall(handle);
|
|
errprintf(1, "%d uspsema failed i %d sp 0x%x",
|
|
get_pid(), i, s[i].sp);
|
|
/* NOTREACHED */
|
|
} else {
|
|
/* didn't get it - we'll select on it */
|
|
FD_SET(s[i].fd[fdidx], &lfd);
|
|
}
|
|
}
|
|
nwait += (nsemas - gotton);
|
|
|
|
/* now wait for any I didn't get */
|
|
while (gotton != nsemas) {
|
|
if (verbose) {
|
|
sprintf(buf, "%s:%d pass %d selecting on %d semas (",
|
|
Cmd,
|
|
get_pid(), j+1,
|
|
nsemas - gotton);
|
|
for (i = 0; i < nsemas; i++)
|
|
if (FD_ISSET(s[i].fd[fdidx], &lfd)) {
|
|
sprintf(sfd, "(%d-%d)",
|
|
s[i].fd[fdidx],
|
|
minor(s[i].dev));
|
|
strcat(buf, sfd);
|
|
}
|
|
strcat(buf, ")\n");
|
|
write(1, buf, strlen(buf));
|
|
}
|
|
tfd = lfd;
|
|
rv = select(FD_SETSIZE, &tfd, NULL, NULL, NULL);
|
|
if (rv < 0) {
|
|
killall(handle);
|
|
errprintf(1, "%d select", get_pid());
|
|
/* NOTREACHED */
|
|
}
|
|
if (verbose)
|
|
sprintf(buf, "%s:%d pass %d got (",
|
|
Cmd, get_pid(), j+1);
|
|
for (i = 0; i < nsemas; i++) {
|
|
if (s[i].fd[fdidx] < 0)
|
|
continue;
|
|
if (FD_ISSET(s[i].fd[fdidx], &tfd)) {
|
|
gotton++;
|
|
FD_CLR(s[i].fd[fdidx], &lfd);
|
|
if (verbose) {
|
|
sprintf(sfd, "%d ",
|
|
s[i].fd[fdidx]);
|
|
strcat(buf, sfd);
|
|
}
|
|
sginap(1);
|
|
if (usvsema(s[i].sp) < 0) {
|
|
killall(handle);
|
|
errprintf(1, "%d usvsema failed i %d sp 0x%x",
|
|
i, get_pid(), s[i].sp);
|
|
/* NOTREACHED */
|
|
}
|
|
}
|
|
}
|
|
if (verbose) {
|
|
strcat(buf, ")\n");
|
|
write(1, buf, strlen(buf));
|
|
}
|
|
}
|
|
|
|
if (verbose)
|
|
printf("%s:%d pass:%d\n", Cmd, get_pid(), j+1);
|
|
}
|
|
/* wait for everyone */
|
|
barrier(sd->b, sd->nusers);
|
|
|
|
/* close semas if unrelated procs */
|
|
if (sd->myturn == whoami || sd->unrel) {
|
|
closesemas(handle, s);
|
|
}
|
|
if (verbose)
|
|
printf("%s:%d complete waited for %d semas\n",
|
|
Cmd, get_pid(), nwait);
|
|
}
|
|
|
|
int
|
|
allocsemas(usptr_t *handle, struct ss *s, int nusers, int whoami)
|
|
{
|
|
register int i;
|
|
struct stat sb;
|
|
|
|
for (i = 0; i < maxsemas-1; i++) {
|
|
if ((s[i].sp = usnewpollsema(handle, 1)) == NULL) {
|
|
/*
|
|
* we can fail due to no more file descriptors
|
|
* if on a Power series we happen to need more locks
|
|
* and don't have a file descriptor available
|
|
* to open the hlock device
|
|
*/
|
|
if (oserror() == ENOMEM || oserror() == EMFILE)
|
|
break;
|
|
killall(handle);
|
|
errprintf(1, "%d usnewpollsema failed i:%d", get_pid(), i);
|
|
}
|
|
|
|
/*
|
|
* for unrelated procs each need their own fds
|
|
*/
|
|
if ((s[i].fd = usmalloc(nusers * sizeof(int), handle)) == NULL) {
|
|
killall(handle);
|
|
errprintf(0, "%d out of memory for fds", get_pid());
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
if ((s[i].fd[whoami] = usopenpollsema(s[i].sp, 0644)) < 0) {
|
|
if (oserror() == EMFILE || oserror() == ENOSPC) {
|
|
usfreepollsema(s[i].sp, handle);
|
|
s[i].sp = NULL;
|
|
break;
|
|
}
|
|
killall(handle);
|
|
errprintf(1, "%d usopenpollsema sp 0x%x",
|
|
get_pid(), s[i].sp);
|
|
}
|
|
if (fstat(s[i].fd[whoami], &sb) != 0) {
|
|
killall(handle);
|
|
errprintf(1, "%d stat on fd %d",
|
|
get_pid(), s[i].fd[whoami]);
|
|
}
|
|
s[i].dev = sb.st_rdev;
|
|
if (debug) {
|
|
usctlsema(s[i].sp, CS_DEBUGON);
|
|
}
|
|
}
|
|
s[i].sp = NULL;
|
|
if (verbose)
|
|
printf("%s:%d allocated %d semaphores (stopped cause:%s)\n",
|
|
Cmd, get_pid(), i, strerror(oserror()));
|
|
return(i);
|
|
}
|
|
|
|
void
|
|
deallocsemas(usptr_t *handle, struct ss *s)
|
|
{
|
|
register int i;
|
|
for (i = 0; ; i++) {
|
|
if (s[i].sp == NULL)
|
|
break;
|
|
if (usfreepollsema(s[i].sp, handle) != 0)
|
|
errprintf(1, "usfreepollsema failed pid %d i %d",
|
|
get_pid(), i);
|
|
usfree(s[i].fd, handle);
|
|
}
|
|
}
|
|
|
|
int
|
|
opensemas(usptr_t *handle, struct ss *s, int whoami)
|
|
{
|
|
register int i, j;
|
|
struct stat sb;
|
|
register int err;
|
|
|
|
for (i = 0; ; i++) {
|
|
if (s[i].sp == NULL)
|
|
break;
|
|
if ((s[i].fd[whoami] = usopenpollsema(s[i].sp, 0644)) < 0) {
|
|
if ((err = oserror()) == EMFILE) {
|
|
break;
|
|
}
|
|
killall(handle);
|
|
errprintf(1, "%d usopenpollsema", get_pid());
|
|
}
|
|
if (fstat(s[i].fd[whoami], &sb) != 0) {
|
|
killall(handle);
|
|
errprintf(1, "%d stat on fd %d", get_pid(),
|
|
s[i].fd[whoami]);
|
|
}
|
|
if (s[i].dev != sb.st_rdev) {
|
|
killall(handle);
|
|
errprintf(0, "dev of sema 0x%x doesn't match dev of fd 0x%x",
|
|
s[i].dev, sb.st_dev);
|
|
/* NOTREACHED */
|
|
}
|
|
}
|
|
/* if we could only open some - mark others as unusable */
|
|
for (j = i; s[j].sp; j++)
|
|
s[j].fd[whoami] = -1;
|
|
|
|
if (verbose) {
|
|
printf("%s:%d opened %d semaphores", Cmd, get_pid(), i);
|
|
if (s[i].sp == NULL)
|
|
printf("\n");
|
|
else
|
|
printf(" (stopped cause:%s)\n", strerror(err));
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
void
|
|
closesemas(usptr_t *handle, struct ss *s)
|
|
{
|
|
register int i;
|
|
for (i = 0; ; i++) {
|
|
if (s[i].sp == NULL)
|
|
break;
|
|
if (usclosepollsema(s[i].sp) < 0) {
|
|
errprintf(1, "usclosepollsema pid %d i %d",
|
|
get_pid(), i);
|
|
/* NOTREACHED */
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ignunlink(char *f)
|
|
{
|
|
register int err = oserror();
|
|
|
|
unlink(f);
|
|
setoserror(err);
|
|
}
|