libc has a number of macros for dealing with thread safety such that it can operate efficiently when single-threaded but Do The Right Thing when multi-threaded. In include/thread_private.h are two sets of macros that look interchangable but that are quite different on the underside.
_MUTEX_LOCK() and _MUTEX_UNLOCK() let libc treat a void* variable as a mutex. They're no-ops unless linked with libpthread. _THREAD_PRIVATE_MUTEX_LOCK() and _THREAD_PRIVATE_MUTEX_UNLOCK() look similar, but require you to declare the mutex with _THREAD_PRIVATE_MUTEX() and have this _THREAD_PRIVATE() extra feature for doing thread-specific data. The trick is that the _THREAD_PRIVATE() feature means _THREAD_PRIVATE_MUTEX_LOCK() is quite a bit more expensive, allocating a couple more chunks of memory and creating a pthread_key_t under the covers, which involves another spin lock, etc. If you're not using the per-thread storage part of _THREAD_PRIVATE* then it's a pile of overhead and over kill. So, diff below converts several uses of _THREAD_PRIVATE_MUTEX_*() to _MUTEX_*(). Regress tests libc/stdio_threading/* and asr/bin/threads still pass with this. ok? Philip Guenther Index: stdio/findfp.c =================================================================== RCS file: /cvs/src/lib/libc/stdio/findfp.c,v retrieving revision 1.18 diff -u -p -r1.18 findfp.c --- stdio/findfp.c 27 Aug 2015 04:37:09 -0000 1.18 +++ stdio/findfp.c 4 Apr 2016 00:47:53 -0000 @@ -56,7 +56,7 @@ static FILE usual[FOPEN_MAX - 3]; static struct __sfileext usualext[FOPEN_MAX - 3]; static struct glue uglue = { 0, FOPEN_MAX - 3, usual }; static struct glue *lastglue = &uglue; -_THREAD_PRIVATE_MUTEX(__sfp_mutex); +static void *sfp_mutex; static struct __sfileext __sFext[3]; FILE __sF[3] = { @@ -108,7 +108,7 @@ __sfp(void) if (!__sdidinit) __sinit(); - _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex); + _MUTEX_LOCK(&sfp_mutex); for (g = &__sglue; g != NULL; g = g->next) { for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) if (fp->_flags == 0) @@ -116,16 +116,16 @@ __sfp(void) } /* release lock while mallocing */ - _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex); + _MUTEX_UNLOCK(&sfp_mutex); if ((g = moreglue(NDYNAMIC)) == NULL) return (NULL); - _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex); + _MUTEX_LOCK(&sfp_mutex); lastglue->next = g; lastglue = g; fp = g->iobs; found: fp->_flags = 1; /* reserve this slot; caller sets real flags */ - _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex); + _MUTEX_UNLOCK(&sfp_mutex); fp->_p = NULL; /* no current pointer */ fp->_w = 0; /* nothing to read or write */ fp->_r = 0; @@ -161,10 +161,10 @@ _cleanup(void) void __sinit(void) { - _THREAD_PRIVATE_MUTEX(__sinit_mutex); + static void *sinit_mutex; int i; - _THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex); + _MUTEX_LOCK(&sinit_mutex); if (__sdidinit) goto out; /* bail out if caller lost the race */ for (i = 0; i < FOPEN_MAX - 3; i++) { @@ -174,5 +174,5 @@ __sinit(void) __atexit_register_cleanup(_cleanup); /* conservative */ __sdidinit = 1; out: - _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex); + _MUTEX_UNLOCK(&sinit_mutex); } Index: stdlib/random.c =================================================================== RCS file: /cvs/src/lib/libc/stdlib/random.c,v retrieving revision 1.29 diff -u -p -r1.29 random.c --- stdlib/random.c 16 Jan 2015 16:48:51 -0000 1.29 +++ stdlib/random.c 4 Apr 2016 00:47:53 -0000 @@ -176,10 +176,11 @@ static int rand_sep = SEP_3; static int random_deterministic; _THREAD_PRIVATE_MUTEX(random); +static void *random_mutex; static long random_l(void); -#define LOCK() _THREAD_PRIVATE_MUTEX_LOCK(random) -#define UNLOCK() _THREAD_PRIVATE_MUTEX_UNLOCK(random) +#define LOCK() _MUTEX_LOCK(&random_mutex) +#define UNLOCK() _MUTEX_UNLOCK(&random_mutex) /* * srandom: Index: asr/res_init.c =================================================================== RCS file: /cvs/src/lib/libc/asr/res_init.c,v retrieving revision 1.9 diff -u -p -r1.9 res_init.c --- asr/res_init.c 23 Mar 2016 18:45:03 -0000 1.9 +++ asr/res_init.c 4 Apr 2016 00:47:53 -0000 @@ -37,7 +37,7 @@ int h_errno; int res_init(void) { - _THREAD_PRIVATE_MUTEX(init); + static void *resinit_mutex; struct asr_ctx *ac; int i; @@ -48,7 +48,7 @@ res_init(void) * structure from the async context, not overriding fields set early * by the user. */ - _THREAD_PRIVATE_MUTEX_LOCK(init); + _MUTEX_LOCK(&resinit_mutex); if (!(_res.options & RES_INIT)) { if (_res.retry == 0) _res.retry = ac->ac_nsretries; @@ -75,7 +75,7 @@ res_init(void) _res.nscount = i; _res.options |= RES_INIT; } - _THREAD_PRIVATE_MUTEX_UNLOCK(init); + _MUTEX_UNLOCK(&resinit_mutex); /* * If the program is not threaded, we want to reflect (some) changes Index: net/res_random.c =================================================================== RCS file: /cvs/src/lib/libc/net/res_random.c,v retrieving revision 1.23 diff -u -p -r1.23 res_random.c --- net/res_random.c 5 Oct 2015 02:57:16 -0000 1.23 +++ net/res_random.c 4 Apr 2016 00:47:53 -0000 @@ -230,12 +230,12 @@ __res_randomid(void) struct timespec ts; pid_t pid; u_int r; - _THREAD_PRIVATE_MUTEX(random); + static void *randomid_mutex; clock_gettime(CLOCK_MONOTONIC, &ts); pid = getpid(); - _THREAD_PRIVATE_MUTEX_LOCK(random); + _MUTEX_LOCK(&randomid_mutex); if (ru_counter >= RU_MAX || ts.tv_sec > ru_reseed || pid != ru_pid) { res_initid(); @@ -248,7 +248,7 @@ __res_randomid(void) r = permute15(ru_seed ^ pmod(ru_g, ru_seed2 + ru_x, RU_N)) | ru_msb; - _THREAD_PRIVATE_MUTEX_UNLOCK(random); + _MUTEX_UNLOCK(&randomid_mutex); return (r); }