diff options
Diffstat (limited to 'bdb/mutex/tm.c')
-rw-r--r-- | bdb/mutex/tm.c | 627 |
1 files changed, 0 insertions, 627 deletions
diff --git a/bdb/mutex/tm.c b/bdb/mutex/tm.c deleted file mode 100644 index 4af1b1907a8..00000000000 --- a/bdb/mutex/tm.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * 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> - -#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY) -#include <pthread.h> -#endif - -#include "db_int.h" - -void exec_proc(); -void tm_file_init(); -void map_file(); -void run_proc(); -void *run_thread(); -void *run_thread_wake(); -void tm_mutex_destroy(); -void tm_mutex_init(); -void tm_mutex_stats(); -void unmap_file(); - -#define MUTEX_WAKEME 0x80 /* Wake-me flag. */ - -DB_ENV dbenv; /* Fake out DB. */ -size_t len; /* Backing file size. */ -int align; /* Mutex alignment in file. */ -int quit; /* End-of-test flag. */ -char *file = "mutex.file"; /* Backing file. */ - -int maxlocks = 20; /* -l: Backing locks. */ -int nlocks = 10000; /* -n: Locks per processes. */ -int nprocs = 20; /* -p: Processes. */ -int child; /* -s: Slave. */ -int nthreads = 1; /* -t: Threads. */ -int verbose; /* -v: Verbosity. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern int optind; - extern char *optarg; - pid_t pid; - int ch, eval, i, status; - char *tmpath; - - tmpath = argv[0]; - while ((ch = getopt(argc, argv, "l:n:p:st:v")) != 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 't': - nthreads = atoi(optarg); -#if !defined(HAVE_MUTEX_PTHREADS) && !defined(BUILD_PTHREADS_ANYWAY) - if (nthreads != 1) { - (void)fprintf(stderr, - "tm: pthreads not available or not compiled for this platform.\n"); - return (EXIT_FAILURE); - } -#endif - break; - case 'v': - verbose = 1; - break; - case '?': - default: - (void)fprintf(stderr, - "usage: tm [-v] [-l maxlocks] [-n locks] [-p procs] [-t threads]\n"); - return (EXIT_FAILURE); - } - argc -= optind; - argv += optind; - - /* - * The file layout: - * DB_MUTEX[1] per-thread mutex array lock - * DB_MUTEX[nthreads] per-thread mutex array - * DB_MUTEX[maxlocks] per-lock mutex array - * u_long[maxlocks][2] per-lock ID array - */ - align = ALIGN(sizeof(DB_MUTEX) * 2, MUTEX_ALIGN); - len = - align * (1 + nthreads + maxlocks) + sizeof(u_long) * maxlocks * 2; - printf( - "mutex alignment %d, structure alignment %d, backing file %lu bytes\n", - MUTEX_ALIGN, align, (u_long)len); - - if (child) { - run_proc(); - return (EXIT_SUCCESS); - } - - tm_file_init(); - tm_mutex_init(); - - printf( - "%d proc, %d threads/proc, %d lock requests from %d locks:\n", - nprocs, nthreads, nlocks, maxlocks); - for (i = 0; i < nprocs; ++i) - switch (fork()) { - case -1: - perror("fork"); - return (EXIT_FAILURE); - case 0: - exec_proc(tmpath); - break; - default: - break; - } - - eval = EXIT_SUCCESS; - while ((pid = wait(&status)) != (pid_t)-1) { - fprintf(stderr, - "%lu: exited %d\n", (u_long)pid, WEXITSTATUS(status)); - if (WEXITSTATUS(status) != 0) - eval = EXIT_FAILURE; - } - - tm_mutex_stats(); - tm_mutex_destroy(); - - printf("tm: exit status: %s\n", - eval == EXIT_SUCCESS ? "success" : "failed!"); - return (eval); -} - -void -exec_proc(tmpath) - char *tmpath; -{ - char *argv[10], **ap, b_l[10], b_n[10], b_t[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"; - sprintf(b_t, "-t%d", nthreads); - *ap++ = b_t; - if (verbose) - *ap++ = "-v"; - - *ap = NULL; - execvp(tmpath, argv); - - fprintf(stderr, "%s: %s\n", tmpath, strerror(errno)); - exit(EXIT_FAILURE); -} - -void -run_proc() -{ -#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY) - pthread_t *kidsp, wakep; - int i, status; - void *retp; -#endif - __os_sleep(&dbenv, 3, 0); /* Let everyone catch up. */ - - srand((u_int)time(NULL) / getpid()); /* Initialize random numbers. */ - - if (nthreads == 1) /* Simple case. */ - exit((int)run_thread((void *)0)); - -#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY) - /* - * Spawn off threads. We have nthreads all locking and going to - * sleep, and one other thread cycling through and waking them up. - */ - if ((kidsp = - (pthread_t *)calloc(sizeof(pthread_t), nthreads)) == NULL) { - fprintf(stderr, "tm: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - for (i = 0; i < nthreads; i++) - if ((errno = pthread_create( - &kidsp[i], NULL, run_thread, (void *)i)) != 0) { - fprintf(stderr, "tm: failed spawning thread %d: %s\n", - i, strerror(errno)); - exit(EXIT_FAILURE); - } - - if ((errno = pthread_create( - &wakep, NULL, run_thread_wake, (void *)0)) != 0) { - fprintf(stderr, "tm: failed spawning wakeup thread: %s\n", - strerror(errno)); - exit(EXIT_FAILURE); - } - - /* Wait for the threads to exit. */ - status = 0; - for (i = 0; i < nthreads; i++) { - pthread_join(kidsp[i], &retp); - if (retp != NULL) { - fprintf(stderr, - "tm: thread %d exited with error\n", i); - status = EXIT_FAILURE; - } - } - free(kidsp); - - /* Signal wakeup thread to stop. */ - quit = 1; - pthread_join(wakep, &retp); - if (retp != NULL) { - fprintf(stderr, "tm: wakeup thread exited with error\n"); - status = EXIT_FAILURE; - } - - exit(status); -#endif -} - -void * -run_thread(arg) - void *arg; -{ - DB_MUTEX *gm_addr, *lm_addr, *tm_addr, *mp; - u_long gid1, gid2, *id_addr; - int fd, i, lock, id, nl, remap; - - /* Set local and global per-thread ID. */ - id = (int)arg; - gid1 = (u_long)getpid(); -#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY) - gid2 = (u_long)pthread_self(); -#else - gid2 = 0; -#endif - printf("\tPID: %lu; TID: %lx; ID: %d\n", gid1, gid2, id); - - nl = nlocks; - for (gm_addr = NULL, remap = 0;;) { - /* Map in the file as necessary. */ - if (gm_addr == NULL) { - map_file(&gm_addr, &tm_addr, &lm_addr, &id_addr, &fd); - remap = (rand() % 100) + 35; - } - - /* Select and acquire a data lock. */ - lock = rand() % maxlocks; - mp = (DB_MUTEX *)((u_int8_t *)lm_addr + lock * align); - if (verbose) - printf("%lu/%lx: %03d\n", gid1, gid2, lock); - - if (__db_mutex_lock(&dbenv, mp)) { - fprintf(stderr, - "%lu/%lx: never got lock\n", gid1, gid2); - return ((void *)EXIT_FAILURE); - } - if (id_addr[lock * 2] != 0) { - fprintf(stderr, - "RACE! (%lu/%lx granted lock %d held by %lu/%lx)\n", - gid1, gid2, - lock, id_addr[lock * 2], id_addr[lock * 2 + 1]); - return ((void *)EXIT_FAILURE); - } - id_addr[lock * 2] = gid1; - id_addr[lock * 2 + 1] = gid2; - - /* - * Pretend to do some work, periodically checking to see if - * we still hold the mutex. - */ - for (i = 0; i < 3; ++i) { - __os_sleep(&dbenv, 0, rand() % 3); - if (id_addr[lock * 2] != gid1 || - id_addr[lock * 2 + 1] != gid2) { - fprintf(stderr, - "RACE! (%lu/%lx stole lock %d from %lu/%lx)\n", - id_addr[lock * 2], - id_addr[lock * 2 + 1], lock, gid1, gid2); - return ((void *)EXIT_FAILURE); - } - } - -#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY) - /* - * Test self-blocking and unlocking by other threads/processes: - * - * acquire the global lock - * set our wakeup flag - * release the global lock - * acquire our per-thread lock - * - * The wakeup thread will wake us up. - */ - if (__db_mutex_lock(&dbenv, gm_addr)) { - fprintf(stderr, "%lu/%lx: global lock\n", gid1, gid2); - return ((void *)EXIT_FAILURE); - } - mp = (DB_MUTEX *)((u_int8_t *)tm_addr + id * align); - F_SET(mp, MUTEX_WAKEME); - if (__db_mutex_unlock(&dbenv, gm_addr)) { - fprintf(stderr, - "%lu/%lx: per-thread wakeup failed\n", gid1, gid2); - return ((void *)EXIT_FAILURE); - } - if (__db_mutex_lock(&dbenv, mp)) { - fprintf(stderr, - "%lu/%lx: per-thread lock\n", gid1, gid2); - return ((void *)EXIT_FAILURE); - } - /* Time passes... */ - if (F_ISSET(mp, MUTEX_WAKEME)) { - fprintf(stderr, "%lu/%lx: %03d wakeup flag still set\n", - gid1, gid2, id); - return ((void *)EXIT_FAILURE); - } -#endif - - /* Release the data lock. */ - id_addr[lock * 2] = id_addr[lock * 2 + 1] = 0; - mp = (DB_MUTEX *)((u_int8_t *)lm_addr + lock * align); - if (__db_mutex_unlock(&dbenv, mp)) { - fprintf(stderr, "%lu/%lx: wakeup failed\n", gid1, gid2); - return ((void *)EXIT_FAILURE); - } - - if (--nl % 100 == 0) - fprintf(stderr, "%lu/%lx: %d\n", gid1, gid2, nl); - - if (nl == 0 || --remap == 0) { - unmap_file((void *)gm_addr, fd); - gm_addr = NULL; - - if (nl == 0) - break; - - __os_sleep(&dbenv, rand() % 3, 0); - } - } - - return (NULL); -} - -#if defined(HAVE_MUTEX_PTHREADS) || defined(BUILD_PTHREADS_ANYWAY) -/* - * run_thread_wake -- - * Thread to wake up other threads that are sleeping. - */ -void * -run_thread_wake(arg) - void *arg; -{ - DB_MUTEX *gm_addr, *tm_addr, *mp; - int fd, id; - - arg = NULL; - map_file(&gm_addr, &tm_addr, NULL, NULL, &fd); - - /* Loop, waking up sleepers and periodically sleeping ourselves. */ - while (!quit) { - id = 0; - - /* Acquire the global lock. */ -retry: if (__db_mutex_lock(&dbenv, gm_addr)) { - fprintf(stderr, "wt: global lock failed\n"); - return ((void *)EXIT_FAILURE); - } - -next: mp = (DB_MUTEX *)((u_int8_t *)tm_addr + id * align); - if (F_ISSET(mp, MUTEX_WAKEME)) { - F_CLR(mp, MUTEX_WAKEME); - if (__db_mutex_unlock(&dbenv, mp)) { - fprintf(stderr, "wt: wakeup failed\n"); - return ((void *)EXIT_FAILURE); - } - } - - if (++id < nthreads && id % 3 != 0) - goto next; - - if (__db_mutex_unlock(&dbenv, gm_addr)) { - fprintf(stderr, "wt: global unlock failed\n"); - return ((void *)EXIT_FAILURE); - } - - __os_sleep(&dbenv, 0, 500); - - if (id < nthreads) - goto retry; - } - return (NULL); -} -#endif - -/* - * tm_file_init -- - * Initialize the backing file. - */ -void -tm_file_init() -{ - int fd; - - - /* Initialize the backing file. */ - printf("Create the backing file...\n"); -#ifdef HAVE_QNX - (void)shm_unlink(file); - if ((fd = shm_open(file, O_CREAT | O_RDWR | O_TRUNC, -#else - (void)remove(file); - if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC, -#endif - - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) { - (void)fprintf(stderr, "%s: open: %s\n", file, strerror(errno)); - exit(EXIT_FAILURE); - } - 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(EXIT_FAILURE); - } - (void)close(fd); -} - -/* - * tm_mutex_init -- - * Initialize the mutexes. - */ -void -tm_mutex_init() -{ - DB_MUTEX *gm_addr, *lm_addr, *mp, *tm_addr; - int fd, i; - - map_file(&gm_addr, &tm_addr, &lm_addr, NULL, &fd); - - printf("Initialize the global mutex...\n"); - if (__db_mutex_init_int(&dbenv, gm_addr, 0, 0)) { - fprintf(stderr, - "__db_mutex_init (global): %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - printf("Initialize the per-thread mutexes...\n"); - for (i = 1, mp = tm_addr; - i <= nthreads; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) { - if (__db_mutex_init_int(&dbenv, mp, 0, MUTEX_SELF_BLOCK)) { - fprintf(stderr, "__db_mutex_init (per-thread %d): %s\n", - i, strerror(errno)); - exit(EXIT_FAILURE); - } - if (__db_mutex_lock(&dbenv, mp)) { - fprintf(stderr, - "__db_mutex_init (per-thread %d) lock: %s\n", - i, strerror(errno)); - exit(EXIT_FAILURE); - } - } - - printf("Initialize the per-lock mutexes...\n"); - for (i = 1, mp = lm_addr; - i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) - if (__db_mutex_init_int(&dbenv, mp, 0, 0)) { - fprintf(stderr, "__db_mutex_init (per-lock: %d): %s\n", - i, strerror(errno)); - exit(EXIT_FAILURE); - } - - unmap_file((void *)gm_addr, fd); -} - -/* - * tm_mutex_destroy -- - * Destroy the mutexes. - */ -void -tm_mutex_destroy() -{ - DB_MUTEX *gm_addr, *lm_addr, *mp, *tm_addr; - int fd, i; - - map_file(&gm_addr, &tm_addr, &lm_addr, NULL, &fd); - - printf("Destroy the global mutex...\n"); - if (__db_mutex_destroy(gm_addr)) { - fprintf(stderr, - "__db_mutex_destroy (global): %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - printf("Destroy the per-thread mutexes...\n"); - for (i = 1, mp = tm_addr; - i <= nthreads; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) { - if (__db_mutex_destroy(mp)) { - fprintf(stderr, - "__db_mutex_destroy (per-thread %d): %s\n", - i, strerror(errno)); - exit(EXIT_FAILURE); - } - } - - printf("Destroy the per-lock mutexes...\n"); - for (i = 1, mp = lm_addr; - i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) - if (__db_mutex_destroy(mp)) { - fprintf(stderr, - "__db_mutex_destroy (per-lock: %d): %s\n", - i, strerror(errno)); - exit(EXIT_FAILURE); - } - - unmap_file((void *)gm_addr, fd); -#ifdef HAVE_QNX - (void)shm_unlink(file); -#endif -} - -/* - * tm_mutex_stats -- - * Display mutex statistics. - */ -void -tm_mutex_stats() -{ - DB_MUTEX *gm_addr, *lm_addr, *mp; - int fd, i; - - map_file(&gm_addr, NULL, &lm_addr, NULL, &fd); - - printf("Per-lock mutex statistics...\n"); - for (i = 1, mp = lm_addr; - i <= maxlocks; ++i, mp = (DB_MUTEX *)((u_int8_t *)mp + align)) - printf("mutex %2d: wait: %lu; no wait %lu\n", i, - (u_long)mp->mutex_set_wait, (u_long)mp->mutex_set_nowait); - - unmap_file((void *)gm_addr, fd); -} - -/* - * map_file -- - * Map in the backing file. - */ -void -map_file(gm_addrp, tm_addrp, lm_addrp, id_addrp, fdp) - DB_MUTEX **gm_addrp, **tm_addrp, **lm_addrp; - u_long **id_addrp; - int *fdp; -{ - void *maddr; - int fd; - -#ifndef MAP_FAILED -#define MAP_FAILED (void *)-1 -#endif -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif -#ifdef HAVE_QNX - if ((fd = shm_open(file, O_RDWR, 0)) == -1) { -#else - if ((fd = open(file, O_RDWR, 0)) == -1) { -#endif - fprintf(stderr, "%s: open %s\n", file, strerror(errno)); - exit(EXIT_FAILURE); - } - - maddr = 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(EXIT_FAILURE); - } - - if (gm_addrp != NULL) - *gm_addrp = (DB_MUTEX *)maddr; - maddr = (u_int8_t *)maddr + align; - if (tm_addrp != NULL) - *tm_addrp = (DB_MUTEX *)maddr; - maddr = (u_int8_t *)maddr + align * nthreads; - if (lm_addrp != NULL) - *lm_addrp = (DB_MUTEX *)maddr; - maddr = (u_int8_t *)maddr + align * maxlocks; - if (id_addrp != NULL) - *id_addrp = (u_long *)maddr; - if (fdp != NULL) - *fdp = fd; -} - -/* - * unmap_file -- - * Discard backing file map. - */ -void -unmap_file(maddr, fd) - void *maddr; - int fd; -{ - if (munmap(maddr, len) != 0) { - fprintf(stderr, "munmap: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - if (close(fd) != 0) { - fprintf(stderr, "close: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } -} |