📄 tm.c
字号:
} /* Time passes... */ if (F_ISSET(tp, MUTEX_WAKEME)) { fprintf(stderr, "%03lu: wakeup flag not cleared\n", id); return ((void *)EXIT_FAILURE); } if (verbose) printf("%03lu: release %d @ %#lx\n", id, lock, (u_long)&mp->mutex); /* Release the data lock. */ mp->id = 0; if (__db_mutex_unlock(&dbenv, &mp->mutex)) { fprintf(stderr, "%03lu: lock release: %s\n", id, strerror(errno)); return ((void *)EXIT_FAILURE); } if (--nl % 100 == 0) fprintf(stderr, "%03lu: %d\n", id, nl); if (nl == 0 || --remap == 0) { if (verbose) printf("%03lu: re-mapping\n", id); unmap_file(gm_addr, fd); gm_addr = NULL; if (nl == 0) break; __os_sleep(&dbenv, 0, rand() % 500); } } return (NULL);}voidrun_wakeup(id) u_long id;{#if defined(MUTEX_THREAD_TEST) pthread_t wakep; int status; void *retp;#endif __os_sleep(&dbenv, 3, 0); /* Let everyone catch up. */ srand((u_int)time(NULL) % getpid()); /* Initialize random numbers. */#if defined(MUTEX_THREAD_TEST) /* * Spawn off wakeup thread. */ if ((errno = pthread_create( &wakep, NULL, run_wthread, (void *)id)) != 0) { fprintf(stderr, "tm: failed spawning wakeup thread: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* * run_locker will create a file when the wakeup thread is no * longer needed. */ status = 0; pthread_join(wakep, &retp); if (retp != NULL) { fprintf(stderr, "tm: wakeup thread exited with error\n"); status = EXIT_FAILURE; } exit(status);#else exit((int)run_wthread((void *)id));#endif}/* * run_wthread -- * Thread to wake up other threads that are sleeping. */void *run_wthread(arg) void *arg;{ struct stat sb; TM *gp, *tp; u_long id, tid; int fd, check_id; u_int8_t *gm_addr, *tm_addr; id = (int)arg;#if defined(MUTEX_THREAD_TEST) tid = (u_long)pthread_self();#else tid = 0;#endif printf("Wakeup: ID %03lu (PID: %lu; TID: %lx)\n", id, (u_long)getpid(), tid); arg = NULL; map_file(&gm_addr, &tm_addr, NULL, &fd); if (verbose) printf("%03lu: map threads @ %#lx\n", id, (u_long)tm_addr); gp = (TM *)gm_addr; /* Loop, waking up sleepers and periodically sleeping ourselves. */ for (check_id = 0;; ++check_id) { /* Check to see if the locking threads have finished. */ if (stat(MT_FILE_QUIT, &sb) == 0) break; /* Check for ID wraparound. */ if (check_id == nthreads * nprocs) check_id = 0; /* Check for a thread that needs a wakeup. */ tp = (TM *)(tm_addr + check_id * align); if (!F_ISSET(tp, MUTEX_WAKEME)) continue; if (verbose) printf("%03lu: wakeup thread %03lu @ %#lx\n", id, tp->id, (u_long)&tp->mutex); /* Acquire the global lock. */ if (__db_mutex_lock(&dbenv, &gp->mutex)) { fprintf(stderr, "wakeup: global lock: %s\n", strerror(errno)); return ((void *)EXIT_FAILURE); } F_CLR(tp, MUTEX_WAKEME); if (__db_mutex_unlock(&dbenv, &tp->mutex)) { fprintf(stderr, "wakeup: unlock: %s\n", strerror(errno)); return ((void *)EXIT_FAILURE); } if (__db_mutex_unlock(&dbenv, &gp->mutex)) { fprintf(stderr, "wakeup: global unlock: %s\n", strerror(errno)); return ((void *)EXIT_FAILURE); } __os_sleep(&dbenv, 0, rand() % 3); } return (NULL);}/* * tm_file_init -- * Initialize the backing file. */voidtm_file_init(){ int fd; /* Initialize the backing file. */ if (verbose) printf("Create the backing file.\n"); (void)shm_unlink(MT_FILE); if ((fd = shm_open( MT_FILE, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1) { (void)fprintf(stderr, "%s: open: %s\n", MT_FILE, strerror(errno)); exit(EXIT_FAILURE); } if (lseek(fd, (off_t)len, SEEK_SET) != (off_t)len || write(fd, &fd, 1) != 1) { (void)fprintf(stderr, "%s: seek/write: %s\n", MT_FILE, strerror(errno)); exit(EXIT_FAILURE); } (void)close(fd);}/* * tm_mutex_init -- * Initialize the mutexes. */voidtm_mutex_init(){ TM *mp; int fd, i; u_int8_t *gm_addr, *lm_addr, *tm_addr; map_file(&gm_addr, &tm_addr, &lm_addr, &fd); if (verbose) printf("init: map threads @ %#lx; locks @ %#lx\n", (u_long)tm_addr, (u_long)lm_addr); if (verbose) printf("Initialize the global mutex:\n"); mp = (TM *)gm_addr; if (__db_mutex_init_int(&dbenv, &mp->mutex, 0, 0)) { fprintf(stderr, "__db_mutex_init (global): %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (verbose) printf("\t@ %#lx\n", (u_long)&mp->mutex); if (verbose) printf( "Initialize %d per-thread mutexes:\n", nthreads * nprocs); for (i = 0; i < nthreads * nprocs; ++i) { mp = (TM *)(tm_addr + i * align); if (__db_mutex_init_int( &dbenv, &mp->mutex, 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->mutex)) { fprintf(stderr, "__db_mutex_lock (per-thread %d): %s\n", i, strerror(errno)); exit(EXIT_FAILURE); } if (verbose) printf("\t@ %#lx\n", (u_long)&mp->mutex); } if (verbose) printf("Initialize %d per-lock mutexes:\n", maxlocks); for (i = 0; i < maxlocks; ++i) { mp = (TM *)(lm_addr + i * align); if (__db_mutex_init_int(&dbenv, &mp->mutex, 0, 0)) { fprintf(stderr, "__db_mutex_init (per-lock: %d): %s\n", i, strerror(errno)); exit(EXIT_FAILURE); } if (verbose) printf("\t@ %#lx\n", (u_long)&mp->mutex); } unmap_file(gm_addr, fd);}/* * tm_mutex_destroy -- * Destroy the mutexes. */voidtm_mutex_destroy(){ TM *gp, *mp; int fd, i; u_int8_t *gm_addr, *lm_addr, *tm_addr; map_file(&gm_addr, &tm_addr, &lm_addr, &fd); if (verbose) printf("Destroy the global mutex.\n"); gp = (TM *)gm_addr; if (__db_mutex_destroy(&gp->mutex)) { fprintf(stderr, "__db_mutex_destroy (global): %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (verbose) printf("Destroy the per-thread mutexes.\n"); for (i = 0; i < nthreads * nprocs; ++i) { mp = (TM *)(tm_addr + i * align); if (__db_mutex_destroy(&mp->mutex)) { fprintf(stderr, "__db_mutex_destroy (per-thread %d): %s\n", i, strerror(errno)); exit(EXIT_FAILURE); } } if (verbose) printf("Destroy the per-lock mutexes.\n"); for (i = 0; i < maxlocks; ++i) { mp = (TM *)(tm_addr + i * align); if (__db_mutex_destroy(&mp->mutex)) { fprintf(stderr, "__db_mutex_destroy (per-lock: %d): %s\n", i, strerror(errno)); exit(EXIT_FAILURE); } } unmap_file(gm_addr, fd); (void)shm_unlink(MT_FILE);}/* * tm_mutex_stats -- * Display mutex statistics. */voidtm_mutex_stats(){ TM *mp; int fd, i; u_int8_t *gm_addr, *lm_addr; map_file(&gm_addr, NULL, &lm_addr, &fd); printf("Per-lock mutex statistics.\n"); for (i = 0; i < maxlocks; ++i) { mp = (TM *)(lm_addr + i * align); printf("mutex %2d: wait: %lu; no wait %lu\n", i, (u_long)mp->mutex.mutex_set_wait, (u_long)mp->mutex.mutex_set_nowait); } unmap_file(gm_addr, fd);}/* * map_file -- * Map in the backing file. */voidmap_file(gm_addrp, tm_addrp, lm_addrp, fdp) u_int8_t **gm_addrp, **tm_addrp, **lm_addrp; int *fdp;{ void *addr; int fd;#ifndef MAP_FAILED#define MAP_FAILED (void *)-1#endif#ifndef MAP_FILE#define MAP_FILE 0#endif if ((fd = shm_open(MT_FILE, O_RDWR, 0)) == -1) { fprintf(stderr, "%s: open %s\n", MT_FILE, strerror(errno)); exit(EXIT_FAILURE); } addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, (off_t)0); if (addr == MAP_FAILED) { fprintf(stderr, "%s: mmap: %s\n", MT_FILE, strerror(errno)); exit(EXIT_FAILURE); } if (gm_addrp != NULL) *gm_addrp = (u_int8_t *)addr; addr = (u_int8_t *)addr + align; if (tm_addrp != NULL) *tm_addrp = (u_int8_t *)addr; addr = (u_int8_t *)addr + align * (nthreads * nprocs); if (lm_addrp != NULL) *lm_addrp = (u_int8_t *)addr; if (fdp != NULL) *fdp = fd;}/* * unmap_file -- * Discard backing file map. */voidunmap_file(addr, fd) u_int8_t *addr; int fd;{ if (munmap(addr, 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); }}/* * usage -- * */intusage(){ (void)fprintf(stderr, "%s\n\t%s\n", "usage: tm [-v] [-l maxlocks]", "[-n locks] [-p procs] [-T locker=ID|wakeup=ID] [-t threads]"); return (EXIT_FAILURE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -