clang-format
This commit is contained in:
@@ -40,46 +40,40 @@
|
||||
/*
|
||||
* comparison functions for qsort
|
||||
*/
|
||||
static
|
||||
int
|
||||
uintcmp(const void *av, const void *bv)
|
||||
{
|
||||
unsigned a = *(const unsigned *)av;
|
||||
unsigned b = *(const unsigned *)bv;
|
||||
static int uintcmp(const void *av, const void *bv) {
|
||||
unsigned a = *(const unsigned *)av;
|
||||
unsigned b = *(const unsigned *)bv;
|
||||
|
||||
if (a < b) {
|
||||
return -1;
|
||||
}
|
||||
if (a > b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (a < b) {
|
||||
return -1;
|
||||
}
|
||||
if (a > b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
altcmp(const void *av, const void *bv)
|
||||
{
|
||||
unsigned a = *(const unsigned *)av;
|
||||
unsigned b = *(const unsigned *)bv;
|
||||
unsigned ax = (a & 0xffff0000) >> 16;
|
||||
unsigned ay = a & 0xffff;
|
||||
unsigned bx = (b & 0xffff0000) >> 16;
|
||||
unsigned by = b & 0xffff;
|
||||
static int altcmp(const void *av, const void *bv) {
|
||||
unsigned a = *(const unsigned *)av;
|
||||
unsigned b = *(const unsigned *)bv;
|
||||
unsigned ax = (a & 0xffff0000) >> 16;
|
||||
unsigned ay = a & 0xffff;
|
||||
unsigned bx = (b & 0xffff0000) >> 16;
|
||||
unsigned by = b & 0xffff;
|
||||
|
||||
if (ax < bx) {
|
||||
return 1;
|
||||
}
|
||||
if (ax > bx) {
|
||||
return -1;
|
||||
}
|
||||
if (ay < by) {
|
||||
return -1;
|
||||
}
|
||||
if (ay > by) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (ax < bx) {
|
||||
return 1;
|
||||
}
|
||||
if (ax > bx) {
|
||||
return -1;
|
||||
}
|
||||
if (ay < by) {
|
||||
return -1;
|
||||
}
|
||||
if (ay > by) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -104,35 +98,29 @@ shuffle(unsigned *p, unsigned n)
|
||||
/*
|
||||
* Compute first differences.
|
||||
*/
|
||||
static
|
||||
void
|
||||
diffs(unsigned *p, unsigned n)
|
||||
{
|
||||
unsigned p0;
|
||||
unsigned i;
|
||||
static void diffs(unsigned *p, unsigned n) {
|
||||
unsigned p0;
|
||||
unsigned i;
|
||||
|
||||
p0 = p[0];
|
||||
p0 = p[0];
|
||||
|
||||
for (i=0; i<n-1; i++) {
|
||||
p[i] = p[i] - p[i+1];
|
||||
}
|
||||
p[n-1] = p[n-1] - p0;
|
||||
for (i = 0; i < n - 1; i++) {
|
||||
p[i] = p[i] - p[i + 1];
|
||||
}
|
||||
p[n - 1] = p[n - 1] - p0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the sum.
|
||||
*/
|
||||
static
|
||||
unsigned
|
||||
sum(const unsigned *p, unsigned n)
|
||||
{
|
||||
unsigned t, i;
|
||||
static unsigned sum(const unsigned *p, unsigned n) {
|
||||
unsigned t, i;
|
||||
|
||||
t = 0;
|
||||
for (i=0; i<n; i++) {
|
||||
t += p[i];
|
||||
}
|
||||
return t;
|
||||
t = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
t += p[i];
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -140,66 +128,64 @@ sum(const unsigned *p, unsigned n)
|
||||
*
|
||||
* Note that this won't work until you have a VM system.
|
||||
*/
|
||||
void
|
||||
grind(unsigned groupid, unsigned id)
|
||||
{
|
||||
unsigned *p;
|
||||
unsigned i, n, s;
|
||||
void grind(unsigned groupid, unsigned id) {
|
||||
unsigned *p;
|
||||
unsigned i, n, s;
|
||||
|
||||
(void)groupid;
|
||||
(void)groupid;
|
||||
|
||||
waitstart();
|
||||
waitstart();
|
||||
|
||||
/* each grind task uses 768K */
|
||||
n = (768*1024) / sizeof(*p);
|
||||
p = malloc(n * sizeof(*p));
|
||||
if (p == NULL) {
|
||||
if (errno == ENOSYS) {
|
||||
/*
|
||||
* If we don't have sbrk, just bail out with
|
||||
* "success" instead of failing the whole
|
||||
* workload.
|
||||
*/
|
||||
errx(0, "grind: sbrk/malloc not implemented");
|
||||
}
|
||||
err(1, "malloc");
|
||||
}
|
||||
/* each grind task uses 768K */
|
||||
n = (768 * 1024) / sizeof(*p);
|
||||
p = malloc(n * sizeof(*p));
|
||||
if (p == NULL) {
|
||||
if (errno == ENOSYS) {
|
||||
/*
|
||||
* If we don't have sbrk, just bail out with
|
||||
* "success" instead of failing the whole
|
||||
* workload.
|
||||
*/
|
||||
errx(0, "grind: sbrk/malloc not implemented");
|
||||
}
|
||||
err(1, "malloc");
|
||||
}
|
||||
|
||||
/* First, get some random integers. */
|
||||
warnx("grind %u: seeding", id);
|
||||
srandom(1753);
|
||||
for (i=0; i<n; i++) {
|
||||
p[i] = random();
|
||||
}
|
||||
/* First, get some random integers. */
|
||||
warnx("grind %u: seeding", id);
|
||||
srandom(1753);
|
||||
for (i = 0; i < n; i++) {
|
||||
p[i] = random();
|
||||
}
|
||||
|
||||
/* Now sort them. */
|
||||
warnx("grind %u: sorting", id);
|
||||
qsort(p, n, sizeof(p[0]), uintcmp);
|
||||
/* Now sort them. */
|
||||
warnx("grind %u: sorting", id);
|
||||
qsort(p, n, sizeof(p[0]), uintcmp);
|
||||
|
||||
/* Sort by a different comparison. */
|
||||
warnx("grind %u: sorting alternately", id);
|
||||
qsort(p, n, sizeof(p[0]), altcmp);
|
||||
/* Sort by a different comparison. */
|
||||
warnx("grind %u: sorting alternately", id);
|
||||
qsort(p, n, sizeof(p[0]), altcmp);
|
||||
|
||||
/* Take the sum. */
|
||||
warnx("grind %u: summing", id);
|
||||
s = sum(p, n);
|
||||
warnx("grind %u: sum is %u (should be %u)", id, s, RIGHT);
|
||||
if (s != RIGHT) {
|
||||
errx(1, "grind %u FAILED", id);
|
||||
}
|
||||
/* Take the sum. */
|
||||
warnx("grind %u: summing", id);
|
||||
s = sum(p, n);
|
||||
warnx("grind %u: sum is %u (should be %u)", id, s, RIGHT);
|
||||
if (s != RIGHT) {
|
||||
errx(1, "grind %u FAILED", id);
|
||||
}
|
||||
|
||||
/* Take first differences. */
|
||||
warnx("grind %u: first differences", id);
|
||||
diffs(p, n);
|
||||
/* Take first differences. */
|
||||
warnx("grind %u: first differences", id);
|
||||
diffs(p, n);
|
||||
|
||||
/* Sort. */
|
||||
warnx("grind %u: sorting", id);
|
||||
qsort(p, n, sizeof(p[0]), uintcmp);
|
||||
/* Sort. */
|
||||
warnx("grind %u: sorting", id);
|
||||
qsort(p, n, sizeof(p[0]), uintcmp);
|
||||
|
||||
warnx("grind %u: summing", id);
|
||||
s = sum(p, n);
|
||||
warnx("grind %u: sum is %u (should be 0)", id, s);
|
||||
if (s != 0) {
|
||||
errx(1, "grind %u FAILED", id);
|
||||
}
|
||||
warnx("grind %u: summing", id);
|
||||
s = sum(p, n);
|
||||
warnx("grind %u: sum is %u (should be 0)", id, s);
|
||||
if (s != 0) {
|
||||
errx(1, "grind %u FAILED", id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,91 +48,81 @@ struct usem startsem;
|
||||
/*
|
||||
* Task hook function that does nothing.
|
||||
*/
|
||||
static
|
||||
void
|
||||
nop(unsigned groupid, unsigned count)
|
||||
{
|
||||
(void)groupid;
|
||||
(void)count;
|
||||
static void nop(unsigned groupid, unsigned count) {
|
||||
(void)groupid;
|
||||
(void)count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for wait.
|
||||
*/
|
||||
static
|
||||
unsigned
|
||||
dowait(pid_t pid)
|
||||
{
|
||||
int r;
|
||||
int status;
|
||||
static unsigned dowait(pid_t pid) {
|
||||
int r;
|
||||
int status;
|
||||
|
||||
r = waitpid(pid, &status, 0);
|
||||
if (r < 0) {
|
||||
err(1, "waitpid");
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
warnx("pid %d signal %d", pid, WTERMSIG(status));
|
||||
return 1;
|
||||
}
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
|
||||
warnx("pid %d exit %d", pid, WEXITSTATUS(status));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
r = waitpid(pid, &status, 0);
|
||||
if (r < 0) {
|
||||
err(1, "waitpid");
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
warnx("pid %d signal %d", pid, WTERMSIG(status));
|
||||
return 1;
|
||||
}
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
|
||||
warnx("pid %d exit %d", pid, WEXITSTATUS(status));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a task group: fork the processes, then wait for them.
|
||||
*/
|
||||
static
|
||||
void
|
||||
runtaskgroup(unsigned count,
|
||||
void (*prep)(unsigned, unsigned),
|
||||
void (*task)(unsigned, unsigned),
|
||||
void (*cleanup)(unsigned, unsigned),
|
||||
unsigned groupid)
|
||||
{
|
||||
pid_t mypids[count];
|
||||
unsigned i;
|
||||
unsigned failures = 0;
|
||||
time_t secs;
|
||||
unsigned long nsecs;
|
||||
static void runtaskgroup(unsigned count, void (*prep)(unsigned, unsigned),
|
||||
void (*task)(unsigned, unsigned),
|
||||
void (*cleanup)(unsigned, unsigned),
|
||||
unsigned groupid) {
|
||||
pid_t mypids[count];
|
||||
unsigned i;
|
||||
unsigned failures = 0;
|
||||
time_t secs;
|
||||
unsigned long nsecs;
|
||||
|
||||
prep(groupid, count);
|
||||
prep(groupid, count);
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
mypids[i] = fork();
|
||||
if (mypids[i] < 0) {
|
||||
err(1, "fork");
|
||||
}
|
||||
if (mypids[i] == 0) {
|
||||
/* child (of second fork) */
|
||||
task(groupid, i);
|
||||
exit(0);
|
||||
}
|
||||
/* parent (of second fork) - continue */
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
mypids[i] = fork();
|
||||
if (mypids[i] < 0) {
|
||||
err(1, "fork");
|
||||
}
|
||||
if (mypids[i] == 0) {
|
||||
/* child (of second fork) */
|
||||
task(groupid, i);
|
||||
exit(0);
|
||||
}
|
||||
/* parent (of second fork) - continue */
|
||||
}
|
||||
|
||||
/*
|
||||
* now wait for the task to finish
|
||||
*/
|
||||
/*
|
||||
* now wait for the task to finish
|
||||
*/
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
failures += dowait(mypids[i]);
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
failures += dowait(mypids[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the end time.
|
||||
*/
|
||||
/*
|
||||
* Store the end time.
|
||||
*/
|
||||
|
||||
__time(&secs, &nsecs);
|
||||
openresultsfile(O_WRONLY);
|
||||
putresult(groupid, secs, nsecs);
|
||||
closeresultsfile();
|
||||
__time(&secs, &nsecs);
|
||||
openresultsfile(O_WRONLY);
|
||||
putresult(groupid, secs, nsecs);
|
||||
closeresultsfile();
|
||||
|
||||
cleanup(groupid, count);
|
||||
cleanup(groupid, count);
|
||||
|
||||
exit(failures ? 1 : 0);
|
||||
exit(failures ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -143,177 +133,150 @@ runtaskgroup(unsigned count,
|
||||
* get timing results even on kernels that don't support waitpid with
|
||||
* WNOHANG.
|
||||
*/
|
||||
static
|
||||
void
|
||||
forkem(unsigned count,
|
||||
void (*prep)(unsigned, unsigned),
|
||||
void (*task)(unsigned, unsigned),
|
||||
void (*cleanup)(unsigned, unsigned),
|
||||
unsigned groupid,
|
||||
pid_t *retpid)
|
||||
{
|
||||
*retpid = fork();
|
||||
if (*retpid < 0) {
|
||||
err(1, "fork");
|
||||
}
|
||||
if (*retpid == 0) {
|
||||
/* child */
|
||||
runtaskgroup(count, prep, task, cleanup, groupid);
|
||||
}
|
||||
/* parent -- just return */
|
||||
static void forkem(unsigned count, void (*prep)(unsigned, unsigned),
|
||||
void (*task)(unsigned, unsigned),
|
||||
void (*cleanup)(unsigned, unsigned), unsigned groupid,
|
||||
pid_t *retpid) {
|
||||
*retpid = fork();
|
||||
if (*retpid < 0) {
|
||||
err(1, "fork");
|
||||
}
|
||||
if (*retpid == 0) {
|
||||
/* child */
|
||||
runtaskgroup(count, prep, task, cleanup, groupid);
|
||||
}
|
||||
/* parent -- just return */
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the task group directors to exit.
|
||||
*/
|
||||
static
|
||||
void
|
||||
waitall(pid_t *pids, unsigned numpids)
|
||||
{
|
||||
unsigned failures = 0;
|
||||
unsigned i;
|
||||
static void waitall(pid_t *pids, unsigned numpids) {
|
||||
unsigned failures = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i=0; i<numpids; i++) {
|
||||
failures += dowait(pids[i]);
|
||||
}
|
||||
if (failures) {
|
||||
errx(1, "TEST FAILURE: one or more subprocesses broke");
|
||||
}
|
||||
for (i = 0; i < numpids; i++) {
|
||||
failures += dowait(pids[i]);
|
||||
}
|
||||
if (failures) {
|
||||
errx(1, "TEST FAILURE: one or more subprocesses broke");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch, compute, and print the timing for one task group.
|
||||
*/
|
||||
static
|
||||
void
|
||||
calcresult(unsigned groupid, time_t startsecs, unsigned long startnsecs,
|
||||
char *buf, size_t bufmax)
|
||||
{
|
||||
time_t secs;
|
||||
unsigned long nsecs;
|
||||
static void calcresult(unsigned groupid, time_t startsecs,
|
||||
unsigned long startnsecs, char *buf, size_t bufmax) {
|
||||
time_t secs;
|
||||
unsigned long nsecs;
|
||||
|
||||
getresult(groupid, &secs, &nsecs);
|
||||
getresult(groupid, &secs, &nsecs);
|
||||
|
||||
/* secs.nsecs -= startsecs.startnsecs */
|
||||
if (nsecs < startnsecs) {
|
||||
nsecs += 1000000000;
|
||||
secs--;
|
||||
}
|
||||
nsecs -= startnsecs;
|
||||
secs -= startsecs;
|
||||
snprintf(buf, bufmax, "%lld.%09lu", (long long)secs, nsecs);
|
||||
/* secs.nsecs -= startsecs.startnsecs */
|
||||
if (nsecs < startnsecs) {
|
||||
nsecs += 1000000000;
|
||||
secs--;
|
||||
}
|
||||
nsecs -= startnsecs;
|
||||
secs -= startsecs;
|
||||
snprintf(buf, bufmax, "%lld.%09lu", (long long)secs, nsecs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by the tasks to wait to start.
|
||||
*/
|
||||
void
|
||||
waitstart(void)
|
||||
{
|
||||
usem_open(&startsem);
|
||||
P(&startsem);
|
||||
usem_close(&startsem);
|
||||
void waitstart(void) {
|
||||
usem_open(&startsem);
|
||||
P(&startsem);
|
||||
usem_close(&startsem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the whole workload.
|
||||
*/
|
||||
static
|
||||
void
|
||||
runit(unsigned numthinkers, unsigned numgrinders,
|
||||
unsigned numponggroups, unsigned ponggroupsize)
|
||||
{
|
||||
pid_t pids[numponggroups + 2];
|
||||
time_t startsecs;
|
||||
unsigned long startnsecs;
|
||||
char buf[32];
|
||||
unsigned i;
|
||||
static void runit(unsigned numthinkers, unsigned numgrinders,
|
||||
unsigned numponggroups, unsigned ponggroupsize) {
|
||||
pid_t pids[numponggroups + 2];
|
||||
time_t startsecs;
|
||||
unsigned long startnsecs;
|
||||
char buf[32];
|
||||
unsigned i;
|
||||
|
||||
printf("Running with %u thinkers, %u grinders, and %u pong groups "
|
||||
"of size %u each.\n", numthinkers, numgrinders, numponggroups,
|
||||
ponggroupsize);
|
||||
printf("Running with %u thinkers, %u grinders, and %u pong groups "
|
||||
"of size %u each.\n",
|
||||
numthinkers, numgrinders, numponggroups, ponggroupsize);
|
||||
|
||||
usem_init(&startsem, STARTSEM);
|
||||
createresultsfile();
|
||||
forkem(numthinkers, nop, think, nop, 0, &pids[0]);
|
||||
forkem(numgrinders, nop, grind, nop, 1, &pids[1]);
|
||||
for (i=0; i<numponggroups; i++) {
|
||||
forkem(ponggroupsize, pong_prep, pong, pong_cleanup, i+2,
|
||||
&pids[i+2]);
|
||||
}
|
||||
usem_open(&startsem);
|
||||
printf("Forking done; starting the workload.\n");
|
||||
__time(&startsecs, &startnsecs);
|
||||
Vn(&startsem, numthinkers + numgrinders +
|
||||
numponggroups * ponggroupsize);
|
||||
waitall(pids, numponggroups + 2);
|
||||
usem_close(&startsem);
|
||||
usem_cleanup(&startsem);
|
||||
usem_init(&startsem, STARTSEM);
|
||||
createresultsfile();
|
||||
forkem(numthinkers, nop, think, nop, 0, &pids[0]);
|
||||
forkem(numgrinders, nop, grind, nop, 1, &pids[1]);
|
||||
for (i = 0; i < numponggroups; i++) {
|
||||
forkem(ponggroupsize, pong_prep, pong, pong_cleanup, i + 2, &pids[i + 2]);
|
||||
}
|
||||
usem_open(&startsem);
|
||||
printf("Forking done; starting the workload.\n");
|
||||
__time(&startsecs, &startnsecs);
|
||||
Vn(&startsem, numthinkers + numgrinders + numponggroups * ponggroupsize);
|
||||
waitall(pids, numponggroups + 2);
|
||||
usem_close(&startsem);
|
||||
usem_cleanup(&startsem);
|
||||
|
||||
openresultsfile(O_RDONLY);
|
||||
openresultsfile(O_RDONLY);
|
||||
|
||||
printf("--- Timings ---\n");
|
||||
if (numthinkers > 0) {
|
||||
calcresult(0, startsecs, startnsecs, buf, sizeof(buf));
|
||||
printf("Thinkers: %s\n", buf);
|
||||
}
|
||||
printf("--- Timings ---\n");
|
||||
if (numthinkers > 0) {
|
||||
calcresult(0, startsecs, startnsecs, buf, sizeof(buf));
|
||||
printf("Thinkers: %s\n", buf);
|
||||
}
|
||||
|
||||
if (numgrinders > 0) {
|
||||
calcresult(1, startsecs, startnsecs, buf, sizeof(buf));
|
||||
printf("Grinders: %s\n", buf);
|
||||
}
|
||||
if (numgrinders > 0) {
|
||||
calcresult(1, startsecs, startnsecs, buf, sizeof(buf));
|
||||
printf("Grinders: %s\n", buf);
|
||||
}
|
||||
|
||||
for (i=0; i<numponggroups; i++) {
|
||||
calcresult(i+2, startsecs, startnsecs, buf, sizeof(buf));
|
||||
printf("Pong group %u: %s\n", i, buf);
|
||||
}
|
||||
for (i = 0; i < numponggroups; i++) {
|
||||
calcresult(i + 2, startsecs, startnsecs, buf, sizeof(buf));
|
||||
printf("Pong group %u: %s\n", i, buf);
|
||||
}
|
||||
|
||||
closeresultsfile();
|
||||
destroyresultsfile();
|
||||
closeresultsfile();
|
||||
destroyresultsfile();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
usage(const char *av0)
|
||||
{
|
||||
warnx("Usage: %s [options]", av0);
|
||||
warnx(" [-t thinkers] set number of thinkers (default 2)");
|
||||
warnx(" [-g grinders] set number of grinders (default 0)");
|
||||
warnx(" [-p ponggroups] set number of pong groups (default 1)");
|
||||
warnx(" [-s ponggroupsize] set pong group size (default 6)");
|
||||
warnx("Thinkers are CPU bound; grinders are memory-bound;");
|
||||
warnx("pong groups are I/O bound.");
|
||||
exit(1);
|
||||
static void usage(const char *av0) {
|
||||
warnx("Usage: %s [options]", av0);
|
||||
warnx(" [-t thinkers] set number of thinkers (default 2)");
|
||||
warnx(" [-g grinders] set number of grinders (default 0)");
|
||||
warnx(" [-p ponggroups] set number of pong groups (default 1)");
|
||||
warnx(" [-s ponggroupsize] set pong group size (default 6)");
|
||||
warnx("Thinkers are CPU bound; grinders are memory-bound;");
|
||||
warnx("pong groups are I/O bound.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned numthinkers = 2;
|
||||
unsigned numgrinders = 0;
|
||||
unsigned numponggroups = 1;
|
||||
unsigned ponggroupsize = 6;
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned numthinkers = 2;
|
||||
unsigned numgrinders = 0;
|
||||
unsigned numponggroups = 1;
|
||||
unsigned ponggroupsize = 6;
|
||||
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
if (!strcmp(argv[i], "-t")) {
|
||||
numthinkers = atoi(argv[++i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-g")) {
|
||||
numgrinders = atoi(argv[++i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-p")) {
|
||||
numponggroups = atoi(argv[++i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-s")) {
|
||||
ponggroupsize = atoi(argv[++i]);
|
||||
}
|
||||
else {
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-t")) {
|
||||
numthinkers = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-g")) {
|
||||
numgrinders = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-p")) {
|
||||
numponggroups = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-s")) {
|
||||
ponggroupsize = atoi(argv[++i]);
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
runit(numthinkers, numgrinders, numponggroups, ponggroupsize);
|
||||
return 0;
|
||||
runit(numthinkers, numgrinders, numponggroups, ponggroupsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
#define MAXCOUNT 64
|
||||
#define PONGLOOPS 1000
|
||||
//#define VERBOSE_PONG
|
||||
// #define VERBOSE_PONG
|
||||
|
||||
static struct usem sems[MAXCOUNT];
|
||||
static unsigned nsems;
|
||||
@@ -55,31 +55,27 @@ static unsigned nsems;
|
||||
* that way each task process has its own file handles and they don't
|
||||
* interfere with each other if file handle locking isn't so great.
|
||||
*/
|
||||
void
|
||||
pong_prep(unsigned groupid, unsigned count)
|
||||
{
|
||||
unsigned i;
|
||||
void pong_prep(unsigned groupid, unsigned count) {
|
||||
unsigned i;
|
||||
|
||||
if (count > MAXCOUNT) {
|
||||
err(1, "pong: too many pongers -- recompile pong.c");
|
||||
}
|
||||
for (i=0; i<count; i++) {
|
||||
usem_init(&sems[i], "sem:pong-%u-%u", groupid, i);
|
||||
}
|
||||
nsems = count;
|
||||
if (count > MAXCOUNT) {
|
||||
err(1, "pong: too many pongers -- recompile pong.c");
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
usem_init(&sems[i], "sem:pong-%u-%u", groupid, i);
|
||||
}
|
||||
nsems = count;
|
||||
}
|
||||
|
||||
void
|
||||
pong_cleanup(unsigned groupid, unsigned count)
|
||||
{
|
||||
unsigned i;
|
||||
void pong_cleanup(unsigned groupid, unsigned count) {
|
||||
unsigned i;
|
||||
|
||||
assert(nsems == count);
|
||||
(void)groupid;
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
usem_cleanup(&sems[i]);
|
||||
}
|
||||
assert(nsems == count);
|
||||
(void)groupid;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
usem_cleanup(&sems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -87,36 +83,33 @@ pong_cleanup(unsigned groupid, unsigned count)
|
||||
* If we're id 0, don't wait the first go so things start, but do
|
||||
* wait the last go.
|
||||
*/
|
||||
static
|
||||
void
|
||||
pong_cyclic(unsigned id)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned nextid;
|
||||
static void pong_cyclic(unsigned id) {
|
||||
unsigned i;
|
||||
unsigned nextid;
|
||||
|
||||
nextid = (id + 1) % nsems;
|
||||
for (i=0; i<PONGLOOPS; i++) {
|
||||
if (i > 0 || id > 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
nextid = (id + 1) % nsems;
|
||||
for (i = 0; i < PONGLOOPS; i++) {
|
||||
if (i > 0 || id > 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
#ifdef VERBOSE_PONG
|
||||
printf(" %u", id);
|
||||
printf(" %u", id);
|
||||
#else
|
||||
if (nextid == 0 && i % 16 == 0) {
|
||||
putchar('.');
|
||||
}
|
||||
if (nextid == 0 && i % 16 == 0) {
|
||||
putchar('.');
|
||||
}
|
||||
#endif
|
||||
V(&sems[nextid]);
|
||||
}
|
||||
if (id == 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
V(&sems[nextid]);
|
||||
}
|
||||
if (id == 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
#ifdef VERBOSE_PONG
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
#else
|
||||
if (nextid == 0) {
|
||||
putchar('\n');
|
||||
}
|
||||
if (nextid == 0) {
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -124,88 +117,80 @@ pong_cyclic(unsigned id)
|
||||
* Pong back and forth. This runs the tasks with middle numbers more
|
||||
* often.
|
||||
*/
|
||||
static
|
||||
void
|
||||
pong_reciprocating(unsigned id)
|
||||
{
|
||||
unsigned i, n;
|
||||
unsigned nextfwd, nextback;
|
||||
unsigned gofwd = 1;
|
||||
static void pong_reciprocating(unsigned id) {
|
||||
unsigned i, n;
|
||||
unsigned nextfwd, nextback;
|
||||
unsigned gofwd = 1;
|
||||
|
||||
if (id == 0) {
|
||||
nextfwd = nextback = 1;
|
||||
n = PONGLOOPS;
|
||||
}
|
||||
else if (id == nsems - 1) {
|
||||
nextfwd = nextback = nsems - 2;
|
||||
n = PONGLOOPS;
|
||||
}
|
||||
else {
|
||||
nextfwd = id + 1;
|
||||
nextback = id - 1;
|
||||
n = PONGLOOPS * 2;
|
||||
}
|
||||
if (id == 0) {
|
||||
nextfwd = nextback = 1;
|
||||
n = PONGLOOPS;
|
||||
} else if (id == nsems - 1) {
|
||||
nextfwd = nextback = nsems - 2;
|
||||
n = PONGLOOPS;
|
||||
} else {
|
||||
nextfwd = id + 1;
|
||||
nextback = id - 1;
|
||||
n = PONGLOOPS * 2;
|
||||
}
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
if (i > 0 || id > 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
if (i > 0 || id > 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
#ifdef VERBOSE_PONG
|
||||
printf(" %u", id);
|
||||
printf(" %u", id);
|
||||
#else
|
||||
if (id == 0 && i % 16 == 0) {
|
||||
putchar('.');
|
||||
}
|
||||
if (id == 0 && i % 16 == 0) {
|
||||
putchar('.');
|
||||
}
|
||||
#endif
|
||||
if (gofwd) {
|
||||
V(&sems[nextfwd]);
|
||||
gofwd = 0;
|
||||
}
|
||||
else {
|
||||
V(&sems[nextback]);
|
||||
gofwd = 1;
|
||||
}
|
||||
}
|
||||
if (id == 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
if (gofwd) {
|
||||
V(&sems[nextfwd]);
|
||||
gofwd = 0;
|
||||
} else {
|
||||
V(&sems[nextback]);
|
||||
gofwd = 1;
|
||||
}
|
||||
}
|
||||
if (id == 0) {
|
||||
P(&sems[id]);
|
||||
}
|
||||
#ifdef VERBOSE_PONG
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
#else
|
||||
if (id == 0) {
|
||||
putchar('\n');
|
||||
}
|
||||
if (id == 0) {
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the pong thing.
|
||||
*/
|
||||
void
|
||||
pong(unsigned groupid, unsigned id)
|
||||
{
|
||||
unsigned idfwd, idback;
|
||||
void pong(unsigned groupid, unsigned id) {
|
||||
unsigned idfwd, idback;
|
||||
|
||||
(void)groupid;
|
||||
(void)groupid;
|
||||
|
||||
idfwd = (id + 1) % nsems;
|
||||
idback = (id + nsems - 1) % nsems;
|
||||
usem_open(&sems[id]);
|
||||
usem_open(&sems[idfwd]);
|
||||
usem_open(&sems[idback]);
|
||||
idfwd = (id + 1) % nsems;
|
||||
idback = (id + nsems - 1) % nsems;
|
||||
usem_open(&sems[id]);
|
||||
usem_open(&sems[idfwd]);
|
||||
usem_open(&sems[idback]);
|
||||
|
||||
waitstart();
|
||||
pong_cyclic(id);
|
||||
waitstart();
|
||||
pong_cyclic(id);
|
||||
#ifdef VERBOSE_PONG
|
||||
printf("--------------------------------\n");
|
||||
printf("--------------------------------\n");
|
||||
#endif
|
||||
pong_reciprocating(id);
|
||||
pong_reciprocating(id);
|
||||
#ifdef VERBOSE_PONG
|
||||
printf("--------------------------------\n");
|
||||
printf("--------------------------------\n");
|
||||
#endif
|
||||
pong_cyclic(id);
|
||||
pong_cyclic(id);
|
||||
|
||||
usem_close(&sems[id]);
|
||||
usem_close(&sems[idfwd]);
|
||||
usem_close(&sems[idback]);
|
||||
usem_close(&sems[id]);
|
||||
usem_close(&sems[idfwd]);
|
||||
usem_close(&sems[idback]);
|
||||
}
|
||||
|
||||
@@ -44,34 +44,30 @@ static int resultsfile = -1;
|
||||
* Create the file that the timing results are written to.
|
||||
* This is done first, in the main process.
|
||||
*/
|
||||
void
|
||||
createresultsfile(void)
|
||||
{
|
||||
int fd;
|
||||
void createresultsfile(void) {
|
||||
int fd;
|
||||
|
||||
assert(resultsfile == -1);
|
||||
assert(resultsfile == -1);
|
||||
|
||||
fd = open(RESULTSFILE, O_RDWR|O_CREAT|O_TRUNC, 0664);
|
||||
if (fd < 0) {
|
||||
err(1, "%s", RESULTSFILE);
|
||||
}
|
||||
if (close(fd) == -1) {
|
||||
warn("%s: close", RESULTSFILE);
|
||||
}
|
||||
fd = open(RESULTSFILE, O_RDWR | O_CREAT | O_TRUNC, 0664);
|
||||
if (fd < 0) {
|
||||
err(1, "%s", RESULTSFILE);
|
||||
}
|
||||
if (close(fd) == -1) {
|
||||
warn("%s: close", RESULTSFILE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the timing results file.
|
||||
* This is done last, in the main process.
|
||||
*/
|
||||
void
|
||||
destroyresultsfile(void)
|
||||
{
|
||||
if (remove(RESULTSFILE) == -1) {
|
||||
if (errno != ENOSYS) {
|
||||
warn("%s: remove", RESULTSFILE);
|
||||
}
|
||||
}
|
||||
void destroyresultsfile(void) {
|
||||
if (remove(RESULTSFILE) == -1) {
|
||||
if (errno != ENOSYS) {
|
||||
warn("%s: remove", RESULTSFILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -80,90 +76,82 @@ destroyresultsfile(void)
|
||||
* then require extra semaphoring to coordinate...) and afterwards
|
||||
* done for reading in the main process.
|
||||
*/
|
||||
void
|
||||
openresultsfile(int openflags)
|
||||
{
|
||||
assert(openflags == O_RDONLY || openflags == O_WRONLY);
|
||||
assert(resultsfile == -1);
|
||||
void openresultsfile(int openflags) {
|
||||
assert(openflags == O_RDONLY || openflags == O_WRONLY);
|
||||
assert(resultsfile == -1);
|
||||
|
||||
resultsfile = open(RESULTSFILE, openflags, 0);
|
||||
if (resultsfile < 0) {
|
||||
err(1, "%s", RESULTSFILE);
|
||||
}
|
||||
resultsfile = open(RESULTSFILE, openflags, 0);
|
||||
if (resultsfile < 0) {
|
||||
err(1, "%s", RESULTSFILE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the timing results file.
|
||||
*/
|
||||
void
|
||||
closeresultsfile(void)
|
||||
{
|
||||
assert(resultsfile >= 0);
|
||||
void closeresultsfile(void) {
|
||||
assert(resultsfile >= 0);
|
||||
|
||||
if (close(resultsfile) == -1) {
|
||||
warn("%s: close", RESULTSFILE);
|
||||
}
|
||||
resultsfile = -1;
|
||||
if (close(resultsfile) == -1) {
|
||||
warn("%s: close", RESULTSFILE);
|
||||
}
|
||||
resultsfile = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a result into the timing results file.
|
||||
*/
|
||||
void
|
||||
putresult(unsigned groupid, time_t secs, unsigned long nsecs)
|
||||
{
|
||||
off_t pos;
|
||||
ssize_t r;
|
||||
void putresult(unsigned groupid, time_t secs, unsigned long nsecs) {
|
||||
off_t pos;
|
||||
ssize_t r;
|
||||
|
||||
assert(resultsfile >= 0);
|
||||
assert(resultsfile >= 0);
|
||||
|
||||
pos = groupid * (sizeof(secs) + sizeof(nsecs));
|
||||
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
|
||||
err(1, "%s: lseek", RESULTSFILE);
|
||||
}
|
||||
r = write(resultsfile, &secs, sizeof(secs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: write (seconds)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(secs)) {
|
||||
errx(1, "%s: write (seconds): Short write", RESULTSFILE);
|
||||
}
|
||||
r = write(resultsfile, &nsecs, sizeof(nsecs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: write (nsecs)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(nsecs)) {
|
||||
errx(1, "%s: write (nsecs): Short write", RESULTSFILE);
|
||||
}
|
||||
pos = groupid * (sizeof(secs) + sizeof(nsecs));
|
||||
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
|
||||
err(1, "%s: lseek", RESULTSFILE);
|
||||
}
|
||||
r = write(resultsfile, &secs, sizeof(secs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: write (seconds)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(secs)) {
|
||||
errx(1, "%s: write (seconds): Short write", RESULTSFILE);
|
||||
}
|
||||
r = write(resultsfile, &nsecs, sizeof(nsecs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: write (nsecs)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(nsecs)) {
|
||||
errx(1, "%s: write (nsecs): Short write", RESULTSFILE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a result from the timing results file.
|
||||
*/
|
||||
void
|
||||
getresult(unsigned groupid, time_t *secs, unsigned long *nsecs)
|
||||
{
|
||||
off_t pos;
|
||||
ssize_t r;
|
||||
void getresult(unsigned groupid, time_t *secs, unsigned long *nsecs) {
|
||||
off_t pos;
|
||||
ssize_t r;
|
||||
|
||||
assert(resultsfile >= 0);
|
||||
assert(resultsfile >= 0);
|
||||
|
||||
pos = groupid * (sizeof(*secs) + sizeof(*nsecs));
|
||||
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
|
||||
err(1, "%s: lseek", RESULTSFILE);
|
||||
}
|
||||
r = read(resultsfile, secs, sizeof(*secs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: read (seconds)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(*secs)) {
|
||||
errx(1, "%s: read (seconds): Unexpected EOF", RESULTSFILE);
|
||||
}
|
||||
r = read(resultsfile, nsecs, sizeof(*nsecs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: read (nsecs)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(*nsecs)) {
|
||||
errx(1, "%s: read (nsecs): Unexpected EOF", RESULTSFILE);
|
||||
}
|
||||
pos = groupid * (sizeof(*secs) + sizeof(*nsecs));
|
||||
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
|
||||
err(1, "%s: lseek", RESULTSFILE);
|
||||
}
|
||||
r = read(resultsfile, secs, sizeof(*secs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: read (seconds)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(*secs)) {
|
||||
errx(1, "%s: read (seconds): Unexpected EOF", RESULTSFILE);
|
||||
}
|
||||
r = read(resultsfile, nsecs, sizeof(*nsecs));
|
||||
if (r < 0) {
|
||||
err(1, "%s: read (nsecs)", RESULTSFILE);
|
||||
}
|
||||
if ((size_t)r < sizeof(*nsecs)) {
|
||||
errx(1, "%s: read (nsecs): Unexpected EOF", RESULTSFILE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,21 +35,19 @@
|
||||
*
|
||||
* All we do is loop.
|
||||
*/
|
||||
void
|
||||
think(unsigned groupid, unsigned id)
|
||||
{
|
||||
volatile unsigned long k, m;
|
||||
volatile unsigned i;
|
||||
void think(unsigned groupid, unsigned id) {
|
||||
volatile unsigned long k, m;
|
||||
volatile unsigned i;
|
||||
|
||||
(void)groupid;
|
||||
(void)id;
|
||||
(void)groupid;
|
||||
(void)id;
|
||||
|
||||
waitstart();
|
||||
waitstart();
|
||||
|
||||
k = 15;
|
||||
m = 7;
|
||||
k = 15;
|
||||
m = 7;
|
||||
#define LOOPCOUNT 35000000
|
||||
for (i=0; i<LOOPCOUNT; i++) {
|
||||
k += k*m;
|
||||
}
|
||||
for (i = 0; i < LOOPCOUNT; i++) {
|
||||
k += k * m;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,87 +41,65 @@
|
||||
|
||||
#include "usem.h"
|
||||
|
||||
void
|
||||
usem_init(struct usem *sem, const char *namefmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
void usem_init(struct usem *sem, const char *namefmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, namefmt);
|
||||
vsnprintf(sem->name, sizeof(sem->name), namefmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, namefmt);
|
||||
vsnprintf(sem->name, sizeof(sem->name), namefmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
sem->fd = open(sem->name, O_RDWR|O_CREAT|O_TRUNC, 0664);
|
||||
if (sem->fd < 0) {
|
||||
err(1, "%s: create", sem->name);
|
||||
}
|
||||
close(sem->fd);
|
||||
sem->fd = -1;
|
||||
sem->fd = open(sem->name, O_RDWR | O_CREAT | O_TRUNC, 0664);
|
||||
if (sem->fd < 0) {
|
||||
err(1, "%s: create", sem->name);
|
||||
}
|
||||
close(sem->fd);
|
||||
sem->fd = -1;
|
||||
}
|
||||
|
||||
void
|
||||
usem_open(struct usem *sem)
|
||||
{
|
||||
sem->fd = open(sem->name, O_RDWR);
|
||||
if (sem->fd < 0) {
|
||||
err(1, "%s: open", sem->name);
|
||||
}
|
||||
void usem_open(struct usem *sem) {
|
||||
sem->fd = open(sem->name, O_RDWR);
|
||||
if (sem->fd < 0) {
|
||||
err(1, "%s: open", sem->name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usem_close(struct usem *sem)
|
||||
{
|
||||
if (close(sem->fd) == -1) {
|
||||
warn("%s: close", sem->name);
|
||||
}
|
||||
void usem_close(struct usem *sem) {
|
||||
if (close(sem->fd) == -1) {
|
||||
warn("%s: close", sem->name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usem_cleanup(struct usem *sem)
|
||||
{
|
||||
(void)remove(sem->name);
|
||||
void usem_cleanup(struct usem *sem) { (void)remove(sem->name); }
|
||||
|
||||
void Pn(struct usem *sem, unsigned count) {
|
||||
ssize_t r;
|
||||
char c[count];
|
||||
|
||||
r = read(sem->fd, c, count);
|
||||
if (r < 0) {
|
||||
err(1, "%s: read", sem->name);
|
||||
}
|
||||
if ((size_t)r < count) {
|
||||
errx(1, "%s: read: unexpected EOF", sem->name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pn(struct usem *sem, unsigned count)
|
||||
{
|
||||
ssize_t r;
|
||||
char c[count];
|
||||
void P(struct usem *sem) { Pn(sem, 1); }
|
||||
|
||||
r = read(sem->fd, c, count);
|
||||
if (r < 0) {
|
||||
err(1, "%s: read", sem->name);
|
||||
}
|
||||
if ((size_t)r < count) {
|
||||
errx(1, "%s: read: unexpected EOF", sem->name);
|
||||
}
|
||||
void Vn(struct usem *sem, unsigned count) {
|
||||
ssize_t r;
|
||||
char c[count];
|
||||
|
||||
/* semfs does not use these values, but be conservative */
|
||||
memset(c, 0, count);
|
||||
|
||||
r = write(sem->fd, c, count);
|
||||
if (r < 0) {
|
||||
err(1, "%s: write", sem->name);
|
||||
}
|
||||
if ((size_t)r < count) {
|
||||
errx(1, "%s: write: Short count", sem->name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
P(struct usem *sem)
|
||||
{
|
||||
Pn(sem, 1);
|
||||
}
|
||||
|
||||
void
|
||||
Vn(struct usem *sem, unsigned count)
|
||||
{
|
||||
ssize_t r;
|
||||
char c[count];
|
||||
|
||||
/* semfs does not use these values, but be conservative */
|
||||
memset(c, 0, count);
|
||||
|
||||
r = write(sem->fd, c, count);
|
||||
if (r < 0) {
|
||||
err(1, "%s: write", sem->name);
|
||||
}
|
||||
if ((size_t)r < count) {
|
||||
errx(1, "%s: write: Short count", sem->name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
V(struct usem *sem)
|
||||
{
|
||||
Vn(sem, 1);
|
||||
}
|
||||
void V(struct usem *sem) { Vn(sem, 1); }
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
* Semaphore structure.
|
||||
*/
|
||||
struct usem {
|
||||
char name[32];
|
||||
int fd;
|
||||
char name[32];
|
||||
int fd;
|
||||
};
|
||||
|
||||
/* XXX this should be in sys/cdefs.h */
|
||||
|
||||
Reference in New Issue
Block a user