roeber%netscape.com e597bf5b5e Import of Sleepycat DB 2.4.14.1
git-svn-id: svn://10.0.0.236/trunk@12863 18797224-902f-48f8-a5cc-f745e15eee43
1998-10-15 03:56:37 +00:00

224 lines
4.8 KiB
C

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997
* Sleepycat Software. All rights reserved.
*/
#include "config.h"
#ifndef lint
static const char sccsid[] = "@(#)test.c 10.4 (Sleepycat) 9/9/97";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
void run_one();
void usage();
#define MMAPFILE "mmap.file"
#define MAXLOCKS 20 /* Number of locks. */
#define NLOCKS 100 /* Number of locks per proc. */
#define NPROCS 5 /* Number of processes. */
int
main(argc, argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
db_mutex_t *marp, *mp;
pid_t pid;
int ch, cnt, fd, maxlock, nlock, nproc, status;
maxlock = MAXLOCKS;
nlock = NLOCKS;
nproc = NPROCS;
while ((ch = getopt(argc, argv, "l:n:p:")) != EOF)
switch(ch) {
case 'l':
maxlock = atoi(optarg);
if (maxlock < 1)
usage();
break;
case 'n':
nlock = atoi(optarg);
if (nlock < 1)
usage();
break;
case 'p':
nproc = atoi(optarg);
if (nproc < 1)
usage();
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
/* Cleanup for debugging. */
unlink(MMAPFILE);
/* Initialize the mutex file. */
(void)printf("Initialize the mutex file...\n");
fd = open(MMAPFILE, O_CREAT | O_RDWR | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd == -1) {
(void)printf("parent: %s: %s\n", MMAPFILE, strerror(errno));
exit(1);
}
if ((marp =
(db_mutex_t *)calloc(maxlock, sizeof(db_mutex_t))) == NULL) {
(void)printf("parent: %s\n", strerror(errno));
exit(1);
}
if (write(fd, marp,
maxlock * sizeof(db_mutex_t)) != maxlock * sizeof(db_mutex_t)) {
(void)printf("parent: write: %s\n", strerror(errno));
exit(1);
}
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif
(void)printf("Mmap the mutex file...\n");
marp = (db_mutex_t *)mmap(NULL, MAXLOCKS * sizeof(db_mutex_t),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0);
if (marp == (db_mutex_t *)MAP_FAILED) {
(void)printf("parent: mmap: %s\n", strerror(errno));
exit(1);
}
/* Initialize the mutexes. */
(void)printf("Initialize the mutexes...\n");
for (cnt = 0, mp = marp; cnt < MAXLOCKS; ++cnt, ++mp)
__db_mutex_init(mp, cnt);
/* Run processes to compete for the locks. */
(void)printf("%s: %d processes: %d requests from %d locks\n",
#ifdef HAVE_SPINLOCKS
"Using spinlocks",
#else
"Using fcntl",
#endif
nproc, nlock, maxlock);
for (cnt = 0; cnt < nproc; ++cnt)
run_one(maxlock, nlock, nproc, fd, marp);
/* Wait for processes to finish. */
(void)printf("Wait for processes...\n");
while ((pid = waitpid(-1, &status, 0)) > 0) {
(void)printf("%d", (int)pid);
if (WIFEXITED(status))
(void)printf(": exited %d", WEXITSTATUS(status));
else if (WIFSIGNALED(status)) {
(void)printf(": signaled %d", WTERMSIG(status));
if (WCOREDUMP(status))
(void)printf(": core dumped");
}
printf("\n");
}
/* Print mutex statistics. */
for (cnt = 0, mp = marp; cnt < MAXLOCKS; ++cnt, ++mp) {
if (mp->mutex_set_wait == 0 && mp->mutex_set_nowait == 0)
continue;
(void)printf("mutex %2d: wait: %2lu; no wait %2lu\n",
cnt, mp->mutex_set_wait, mp->mutex_set_nowait);
}
#ifdef MUTEX_DESTROY
/* Discard mutexes. */
(void)printf("Discard mutexes...\n");
for (cnt = 0, mp = marp; cnt < MAXLOCKS; ++cnt, ++mp)
if (__db_mutex_destroy(mp))
perror("db_mutex_destroy");
#endif
/* Close the file descriptor. */
(void)close(fd);
/* Lose the mmap'd file. */
(void)munmap((caddr_t)mp, sizeof(db_mutex_t));
(void)unlink(MMAPFILE);
exit(0);
}
void
run_one(maxlock, nlock, nproc, fd, mp)
int maxlock, nlock, nproc, fd;
db_mutex_t *mp;
{
pid_t mypid;
int lock;
char buf[128];
/* Create a new process. */
if (nproc > 1)
switch (fork()) {
case -1:
perror("fork");
exit (1);
case 0:
break;
default:
return;
}
mypid = getpid();
srand(time(NULL) / mypid);
while (nlock--) {
lock = rand() % maxlock;
#define VERBOSE
#ifdef VERBOSE
(void)sprintf(buf, "%d %d\n", (int)mypid, lock);
write(1, buf, strlen(buf));
#endif
if (__db_mutex_lock(mp + lock, fd, NULL)) {
(void)printf("child %d: never got lock\n", (int)mypid);
goto err;
}
mp[lock].pid = mypid;
sleep(rand() & 2);
if (mypid != mp[lock].pid) {
(void)printf("child %d: RACE!\n", (int)mypid);
goto err;
}
if (__db_mutex_unlock(mp + lock, fd)) {
(void)printf("child %d: wakeup failed\n", (int)mypid);
goto err;
}
}
exit(0);
err: close(fd);
exit(1);
}
void
usage()
{
(void)fprintf(stderr,
"usage: run [-l max_locks] [-n locks] [-p procs]\n");
exit (1);
}