diff options
author | jbj <devnull@localhost> | 2001-05-13 19:58:25 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2001-05-13 19:58:25 +0000 |
commit | 2af040895b279eca8fb5a44240da7e42c8b4ac66 (patch) | |
tree | 1b74621cfd1f4531a39786c4b06a59bc0e92dbf7 /db/mutex | |
parent | 9b44f1b7168b70652f7fad2e0da6fdade4b965d7 (diff) | |
download | rpm-2af040895b279eca8fb5a44240da7e42c8b4ac66.tar.gz rpm-2af040895b279eca8fb5a44240da7e42c8b4ac66.tar.bz2 rpm-2af040895b279eca8fb5a44240da7e42c8b4ac66.zip |
Initial revision
CVS patchset: 4782
CVS date: 2001/05/13 19:58:25
Diffstat (limited to 'db/mutex')
-rw-r--r-- | db/mutex/tm.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/db/mutex/tm.c b/db/mutex/tm.c new file mode 100644 index 000000000..e866981ec --- /dev/null +++ b/db/mutex/tm.c @@ -0,0 +1,340 @@ +/* + * Standalone mutex tester for Berkeley DB mutexes. + */ +#include "db_config.h" + +#include <sys/types.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> + +#include "db_int.h" + +void exec_one(); +void file_init(); +void map_file(); +void mutex_destroy(); +void mutex_init(); +void mutex_stats(); +void run_one(); +void unmap_file(); + +int align; /* Mutex alignment in file. */ +DB_ENV dbenv; /* Fake out DB. */ +char *file = "mutex.file"; /* Backing file. */ +size_t len; /* Backing file size. */ +int maxlocks = 20; /* -l: Backing locks. */ +int nlocks = 10000; /* -n: Locks per processes. */ +int nprocs = 20; /* -p: Processes. */ +int child; /* -s: Slave. */ +int verbose; /* -v: Verbosity. */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + extern char *optarg; + pid_t pid; + int ch, i, status; + + while ((ch = getopt(argc, argv, "l:n:p:sv")) != EOF) + switch(ch) { + case 'l': + maxlocks = atoi(optarg); + break; + case 'n': + nlocks = atoi(optarg); + break; + case 'p': + nprocs = atoi(optarg); + break; + case 's': + child = 1; + break; + case 'v': + verbose = 1; + break; + case '?': + default: + (void)fprintf(stderr, + "usage: %s [-l maxlocks] [-n locks] [-p procs]\n", + argv[0]); + exit(1); + } + argc -= optind; + argv += optind; + + /* + * Needed to figure out the file layout. + */ + align = ALIGN(sizeof(MUTEX) * 2, MUTEX_ALIGN); + len = align * maxlocks + sizeof(u_int32_t) * maxlocks; + + /* + * Hack DBENV to work. + */ + dbenv.db_mutexlocks = 1; + + if (child) { + run_one(); + exit(0); + } + + file_init(); + mutex_init(); + + printf("Run: %d processes (%d requests from %d locks):", + nprocs, nlocks, maxlocks); + for (i = 0; i < nprocs; ++i) + switch (pid = fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + exec_one(); + break; + default: + printf(" %lu", (u_long)pid); + break; + } + printf("\n"); + + while ((pid = wait(&status)) != (pid_t)-1) + printf("%d: exited %d\n", pid, WEXITSTATUS(status)); + fflush(stdout); + + printf("Statistics...\n"); + mutex_stats(); + + mutex_destroy(); + + exit(0); +} + +void +exec_one() +{ + char *argv[10], **ap, b_l[10], b_n[10]; + + ap = &argv[0]; + *ap++ = "tm"; + sprintf(b_l, "-l%d", maxlocks); + *ap++ = b_l; + sprintf(b_n, "-n%d", nlocks); + *ap++ = b_n; + *ap++ = "-s"; + if (verbose) + *ap++ = "-v"; + *ap = NULL; + execv("./tm", argv); + + fprintf(stderr, "./tm: %s\n", strerror(errno)); + exit(1); +} + +void +run_one() +{ + MUTEX *maddr, *mp; + pid_t pid, *pidlist; + int fd, i, lock, remap; + char buf[128]; + + __os_sleep(&dbenv, 3, 0); /* Let everyone catch up. */ + + pid = getpid(); + srand((u_int)time(NULL) / pid); + + for (maddr = NULL;;) { + if (maddr == NULL) { + map_file(&maddr, &fd); + pidlist = + (pid_t *)((u_int8_t *)maddr + align * maxlocks); + remap = (rand() % 100) + 35; + + if (verbose) + printf("%lu: map @ %lx\n", + (u_long)pid, (u_long)maddr); + } + + lock = rand() % maxlocks; + if (verbose) { + (void)sprintf(buf, + "%lu %lu:\n", (u_long)pid, (u_long)lock); + write(1, buf, strlen(buf)); + } + mp = (MUTEX *)((u_int8_t *)maddr + lock * align); + if (__db_mutex_lock(&dbenv, mp, fd)) { + fprintf(stderr, "%lu: never got lock\n", (u_long)pid); + exit(1); + } + if (pidlist[lock] != 0) { + fprintf(stderr, + "RACE! (%lu granted lock %d held by %lu)\n", + (u_long)pid, lock, (u_long)pidlist[lock]); + exit(1); + } + pidlist[lock] = pid; + for (i = 0; i < 3; ++i) { + __os_sleep(&dbenv, 0, rand() % 50); + if (pidlist[lock] != pid) { + fprintf(stderr, + "RACE! (%lu stole lock %d from %lu)\n", + (u_long)pidlist[lock], lock, (u_long)pid); + exit(1); + } + } + pidlist[lock] = 0; + if (__db_mutex_unlock(&dbenv, mp)) { + fprintf(stderr, "%d: wakeup failed\n", pid); + exit(1); + } + + if (--remap == 0 || --nlocks == 0) { + unmap_file(maddr, fd); + maddr = NULL; + if (verbose) + printf("%lu: unmap\n", (u_long)pid); + + __os_sleep(&dbenv, rand() % 3, 0); + + if (nlocks == 0) + break; + } + + if (nlocks % 100 == 0) + write(1, ".", 1); + } + + exit(0); +} + +void +file_init() +{ + int fd; + + printf("Initialize the backing file...\n"); + + /* + * Initialize the backing file. + * + * Find out how much space we need to correctly align maxlocks locks + * plus maxlocks check words and create the file. + */ + (void)unlink(file); + if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) { + (void)fprintf(stderr, "%s: %s\n", file, strerror(errno)); + exit(1); + } + if (lseek(fd, (off_t)len, SEEK_SET) != len || write(fd, &fd, 1) != 1) { + (void)fprintf(stderr, + "%s: seek/write: %s\n", file, strerror(errno)); + exit(1); + } + (void)close(fd); +} + +void +mutex_init() +{ + MUTEX *maddr, *mp; + int fd, i; + + printf("Initialize the mutexes...\n"); + map_file(&maddr, &fd); + for (i = 0, mp = maddr; + i < maxlocks; ++i, mp = (MUTEX *)((u_int8_t *)mp + align)) + if (__db_mutex_init(&dbenv, mp, 0, 0)) { + fprintf(stderr, "__db_mutex_init (%d): %s\n", + i + 1, strerror(errno)); + exit(1); + } + unmap_file(maddr, fd); +} + +void +mutex_destroy() +{ + MUTEX *maddr, *mp; + int fd, i; + + map_file(&maddr, &fd); + for (i = 0, mp = maddr; + i < maxlocks; ++i, mp = (MUTEX *)((u_int8_t *)mp + align)) + if (__db_mutex_destroy(mp)) { + fprintf(stderr, "__db_mutex_destroy (%d): %s\n", + i + 1, strerror(errno)); + exit(1); + } + unmap_file(maddr, fd); +} + +void +mutex_stats() +{ + MUTEX *maddr, *mp; + int fd, i; + + map_file(&maddr, &fd); + for (i = 0, mp = maddr; + i < maxlocks; ++i, mp = (MUTEX *)((u_int8_t *)mp + align)) + printf("mutex %2d: wait: %2lu; no wait %2lu\n", i, + (u_long)mp->mutex_set_wait, (u_long)mp->mutex_set_nowait); + unmap_file(maddr, fd); +} + +void +map_file(maddrp, fdp) + MUTEX **maddrp; + int *fdp; +{ + MUTEX *maddr; + int fd; + +#ifndef MAP_FAILED +#define MAP_FAILED (MUTEX *)-1 +#endif +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + if ((fd = open(file, O_RDWR, 0)) == -1) { + fprintf(stderr, "%s: open %s\n", file, strerror(errno)); + exit(1); + } + + maddr = (MUTEX *)mmap(NULL, len, + PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, (off_t)0); + if (maddr == MAP_FAILED) { + fprintf(stderr, "%s: mmap: %s\n", file, strerror(errno)); + exit(1); + } + + *maddrp = maddr; + *fdp = fd; +} + +void +unmap_file(maddr, fd) + MUTEX *maddr; + int fd; +{ + if (munmap(maddr, len) != 0) { + fprintf(stderr, "munmap: %s\n", strerror(errno)); + exit(1); + } + if (close(fd) != 0) { + fprintf(stderr, "close: %s\n", strerror(errno)); + exit(1); + } +} |