/* randomize nonce */ void nonce_init(void) { int fd, n; if ((fd = open("/dev/random", O_RDONLY)) == -1) { mlog(LOG_CRIT, "%s: open(/dev/random): %s", __func__, strerror(errno)); exit(1); } /* streamid must be non-zero */ while (streamid[0] == 0 && streamid[1] == 0) { if ((n = read(fd, streamid, sizeof(streamid))) == -1) { mlog(LOG_CRIT, "%s: read: %s", __func__, strerror(errno)); exit(1); } if (n < (int) sizeof(streamid)) { mlog(LOG_CRIT, "%s: short read", __func__); exit(1); } } (void) close(fd); #ifndef HAVE_ATOMIC_H xpthread_mutex_init(&seq_mutex, NULL); #endif /* initialize to -2 so that first increment gives seq 0 */ seq = -2; }
static void * thr_func (void *arg) { long long int i; for (i = 0; i < iteration_count; i++) { if ((uintptr_t) arg == 0) { xpthread_mutex_destroy (&mutex); xpthread_mutex_init (&mutex, NULL); } xpthread_barrier_wait (&barrier); /* Test if enabling lock elision works if it is enabled concurrently. There was a race in FORCE_ELISION macro which leads to either pthread_mutex_destroy returning EBUSY as the owner was recorded by pthread_mutex_lock - in "normal mutex" code path - but was not resetted in pthread_mutex_unlock - in "elision" code path. Or it leads to the assertion in nptl/pthread_mutex_lock.c: assert (mutex->__data.__owner == 0); Please ensure that the test is run with lock elision: export GLIBC_TUNABLES=glibc.elision.enable=1 */ xpthread_mutex_lock (&mutex); xpthread_mutex_unlock (&mutex); xpthread_barrier_wait (&barrier); } return NULL; }
static int do_test (void) { unsigned int i; printf ("Starting %d threads to run %lld iterations.\n", thread_count, iteration_count); pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t)); xpthread_barrier_init (&barrier, NULL, thread_count); xpthread_mutex_init (&mutex, NULL); for (i = 0; i < thread_count; i++) threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i); for (i = 0; i < thread_count; i++) xpthread_join (threads[i]); xpthread_barrier_destroy (&barrier); free (threads); return EXIT_SUCCESS; }