diff options
| author | raf <none@none> | 2007-03-20 17:29:57 -0700 |
|---|---|---|
| committer | raf <none@none> | 2007-03-20 17:29:57 -0700 |
| commit | cb6207858a9fcc2feaee22e626912fba281ac969 (patch) | |
| tree | 9e84b682e42e9c8dcd013b29690be6905e45841d /usr/src/lib/libc/port/threads/tsd.c | |
| parent | d7306b64c847d897abb9ece8624fca9cf28d358f (diff) | |
| download | illumos-joyent-cb6207858a9fcc2feaee22e626912fba281ac969.tar.gz | |
PSARC 2007/129 thr_keycreate_once
6513516 double checked locking code needs a memory barrier
Diffstat (limited to 'usr/src/lib/libc/port/threads/tsd.c')
| -rw-r--r-- | usr/src/lib/libc/port/threads/tsd.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/usr/src/lib/libc/port/threads/tsd.c b/usr/src/lib/libc/port/threads/tsd.c index 11484f6763..ac89be862d 100644 --- a/usr/src/lib/libc/port/threads/tsd.c +++ b/usr/src/lib/libc/port/threads/tsd.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -128,6 +128,47 @@ _thr_keycreate(thread_key_t *pkey, void (*destructor)(void *)) return (0); } +/* + * Same as _thr_keycreate(), above, except that the key creation + * is performed only once. This relies upon the fact that a key + * value of THR_ONCE_KEY is invalid, and requires that the key be + * allocated with a value of THR_ONCE_KEY before calling here. + * THR_ONCE_KEY and PTHREAD_ONCE_KEY_NP, defined in <thread.h> + * and <pthread.h> respectively, must have the same value. + * Example: + * + * static pthread_key_t key = PTHREAD_ONCE_KEY_NP; + * ... + * pthread_key_create_once_np(&key, destructor); + */ +#pragma weak pthread_key_create_once_np = _thr_keycreate_once +#pragma weak _pthread_key_create_once_np = _thr_keycreate_once +#pragma weak thr_keycreate_once = _thr_keycreate_once +int +_thr_keycreate_once(thread_key_t *keyp, void (*destructor)(void *)) +{ + static mutex_t key_lock = DEFAULTMUTEX; + thread_key_t key; + int error; + + if (*keyp == THR_ONCE_KEY) { + lmutex_lock(&key_lock); + if (*keyp == THR_ONCE_KEY) { + error = _thr_keycreate(&key, destructor); + if (error) { + lmutex_unlock(&key_lock); + return (error); + } + _membar_producer(); + *keyp = key; + } + lmutex_unlock(&key_lock); + } + _membar_consumer(); + + return (0); +} + #pragma weak pthread_key_delete = _thr_key_delete #pragma weak _pthread_key_delete = _thr_key_delete int |
