summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/mt_misc.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2010-03-10 13:23:25 +0000
committerjhb <jhb@FreeBSD.org>2010-03-10 13:23:25 +0000
commite0724fd324c89b8c46185fe402fd332141ea5bf5 (patch)
treedae7801acd654dfe736481930016ad68270d7757 /lib/libc/rpc/mt_misc.c
parent42dc39ae95f85b0f1bedbdfa406342f9ac3e4fcc (diff)
downloadFreeBSD-src-e0724fd324c89b8c46185fe402fd332141ea5bf5.zip
FreeBSD-src-e0724fd324c89b8c46185fe402fd332141ea5bf5.tar.gz
Use thr_once() with once_t controls to initialize various thread_key_t
objects used to provide per-thread storage in the RPC code. Almost all of these used double-checking with a dedicated mutex (tsd_lock) to do this before. However, that is not always safe with more relaxed memory orders. There were also other bugs, such as one in __rpc_createrr() that caused a new key to be allocated each time __rpc_createrr() was invoked. PR: threads/144558 Reported by: Sam Robb samrobb of averesystems com (key leak) MFC after: 1 week
Diffstat (limited to 'lib/libc/rpc/mt_misc.c')
-rw-r--r--lib/libc/rpc/mt_misc.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/lib/libc/rpc/mt_misc.c b/lib/libc/rpc/mt_misc.c
index 6241611..7abcaed 100644
--- a/lib/libc/rpc/mt_misc.c
+++ b/lib/libc/rpc/mt_misc.c
@@ -28,7 +28,6 @@ __FBSDID("$FreeBSD$");
#define proglst_lock __proglst_lock
#define rpcsoc_lock __rpcsoc_lock
#define svcraw_lock __svcraw_lock
-#define tsd_lock __tsd_lock
#define xprtlist_lock __xprtlist_lock
/* protects the services list (svc.c) */
@@ -76,33 +75,33 @@ pthread_mutex_t rpcsoc_lock = PTHREAD_MUTEX_INITIALIZER;
/* svc_raw.c serialization */
pthread_mutex_t svcraw_lock = PTHREAD_MUTEX_INITIALIZER;
-/* protects TSD key creation */
-pthread_mutex_t tsd_lock = PTHREAD_MUTEX_INITIALIZER;
-
/* xprtlist (svc_generic.c) */
pthread_mutex_t xprtlist_lock = PTHREAD_MUTEX_INITIALIZER;
#undef rpc_createerr
struct rpc_createerr rpc_createerr;
+static thread_key_t rce_key;
+static once_t rce_once = ONCE_INITIALIZER;
+static int rce_key_error;
+
+static void
+rce_key_init(void)
+{
+
+ rce_key_error = thr_keycreate(&rce_key, free);
+}
struct rpc_createerr *
__rpc_createerr()
{
- static thread_key_t rce_key = 0;
struct rpc_createerr *rce_addr = 0;
if (thr_main())
return (&rpc_createerr);
- if ((rce_addr =
- (struct rpc_createerr *)thr_getspecific(rce_key)) != 0) {
- mutex_lock(&tsd_lock);
- if (thr_keycreate(&rce_key, free) != 0) {
- mutex_unlock(&tsd_lock);
- return (&rpc_createerr);
- }
- mutex_unlock(&tsd_lock);
- }
+ if (thr_once(&rce_once, rce_key_init) != 0 || rce_key_error != 0)
+ return (&rpc_createerr);
+ rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key);
if (!rce_addr) {
rce_addr = (struct rpc_createerr *)
malloc(sizeof (struct rpc_createerr));
OpenPOWER on IntegriCloud