diff options
Diffstat (limited to 'lib/libpthread/thread')
-rw-r--r-- | lib/libpthread/thread/Makefile.inc | 4 | ||||
-rw-r--r-- | lib/libpthread/thread/thread_storage.c | 82 | ||||
-rw-r--r-- | lib/libpthread/thread/thread_tag.c | 120 |
3 files changed, 122 insertions, 84 deletions
diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc index 074139f176b..2545995b494 100644 --- a/lib/libpthread/thread/Makefile.inc +++ b/lib/libpthread/thread/Makefile.inc @@ -1,5 +1,5 @@ -# $OpenBSD: Makefile.inc,v 1.5 2003/01/20 18:12:11 marc Exp $ +# $OpenBSD: Makefile.inc,v 1.6 2004/06/07 21:11:23 marc Exp $ .PATH: ${SRCDIR}/thread -SRCS+= thread_storage.c thread_malloc_lock.c +SRCS+= thread_tag.c thread_malloc_lock.c diff --git a/lib/libpthread/thread/thread_storage.c b/lib/libpthread/thread/thread_storage.c deleted file mode 100644 index 61609f9c277..00000000000 --- a/lib/libpthread/thread/thread_storage.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $OpenBSD: thread_storage.c,v 1.6 2002/11/05 22:19:55 marc Exp $ */ -/* Public Domain */ - -/* - * libpthread's stronger functions - */ - -#include <stdlib.h> -#include <pthread.h> -#include <string.h> -#include "pthread_private.h" - -void -_libc_private_storage_lock(mutex) - pthread_mutex_t *mutex; -{ - if (__isthreaded && pthread_mutex_lock(mutex) != 0) - PANIC("_libc_private_storage_lock"); -} - -void -_libc_private_storage_unlock(mutex) - pthread_mutex_t *mutex; -{ - if (__isthreaded && pthread_mutex_unlock(mutex) != 0) - PANIC("_libc_private_storage_unlock"); -} - -void * -_libc_private_storage(volkey, init, initsz, error) - volatile struct _thread_private_key_struct * volkey; - void * init; - size_t initsz; - void * error; -{ - void *result; - void (*cleanfn)(void *); - struct _thread_private_key_struct * key; - - /* Use static storage while not threaded: */ - if (!__isthreaded) - return init; - - key = (struct _thread_private_key_struct *)volkey; /* for gcc */ - - /* Create the key once: */ - if (volkey->once.state == PTHREAD_NEEDS_INIT) { - if (pthread_mutex_lock(&key->once.mutex) != 0) - return error; - if (volkey->once.state == PTHREAD_NEEDS_INIT) { - if (key->cleanfn == NULL) - cleanfn = free; - else - cleanfn = key->cleanfn; - if (pthread_key_create(&key->key, cleanfn) != 0) { - pthread_mutex_unlock(&key->once.mutex); - return error; - } - key->once.state = PTHREAD_DONE_INIT; - } - pthread_mutex_unlock(&key->once.mutex); - } - - /* XXX signals may cause re-entrancy here? */ - - /* Acquire this key's thread-specific storage: */ - result = pthread_getspecific(key->key); - - /* Allocate and initialise storage if unallocated: */ - if (result == NULL) { - result = malloc(initsz); - if (result == NULL) - return error; - if (pthread_setspecific(key->key, result) != 0) { - free(result); - return error; - } - memcpy(result, init, initsz); - } - - return result; -} diff --git a/lib/libpthread/thread/thread_tag.c b/lib/libpthread/thread/thread_tag.c new file mode 100644 index 00000000000..43bd4c14b0e --- /dev/null +++ b/lib/libpthread/thread/thread_tag.c @@ -0,0 +1,120 @@ +/* $OpenBSD: thread_tag.c,v 1.1 2004/06/07 21:11:23 marc Exp $ */ + +/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ + +#include <sys/time.h> + +#include <stdlib.h> + +#include "thread_private.h" +#include "pthread.h" +#include "pthread_private.h" + +/* + * A thread tag is a pointer to a structure of this time. An opaque + * tag is used to decouple libc from the thread library. + */ +struct _thread_tag { + pthread_mutex_t m; /* the tag's mutex */ + pthread_key_t k; /* a key for private data */ +}; + +/* + * local mutex to protect against tag creation races. + */ +static pthread_mutex_t _thread_tag_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * Initialize a thread tag structure once. This function is called + * if the tag is null. Allocation and initialization are controlled + * by a mutex. If the tag is not null when the mutex is obtained + * the caller lost a race -- some other thread initialized the tag. + * This function will never return NULL. + */ +static void +_thread_tag_init(void **tag) +{ + struct _thread_tag *tt; + int result; + + result = pthread_mutex_lock(&_thread_tag_mutex); + if (result == 0) { + if (*tag == NULL) { + tt = malloc(sizeof *tt); + if (tt != NULL) { + result = pthread_mutex_init(&tt->m, NULL); + result |= pthread_key_create(&tt->k, free); + *tag = tt; + } + } + result |= pthread_mutex_unlock(&_thread_tag_mutex); + } + if (result != 0) + PANIC(__func__); +} + +/* + * lock the mutex associated with the given tag + */ +void +_thread_tag_lock(void **tag) +{ + struct _thread_tag *tt; + + if (__isthreaded) { + if (*tag == NULL) + _thread_tag_init(tag); + tt = *tag; + if (pthread_mutex_lock(&tt->m) != 0) + PANIC(__func__); + } +} + +/* + * unlock the mutex associated with the given tag + */ +void +_thread_tag_unlock(void **tag) +{ + struct _thread_tag *tt; + + if (__isthreaded) { + if (*tag == NULL) + _thread_tag_init(tag); + tt = *tag; + if (pthread_mutex_unlock(&tt->m) != 0) + PANIC(__func__); + } +} + +/* + * return the thread specific data for the given tag. If there + * is no date for this thread initialize it from 'storage'. + * On any error return 'err'. + */ +void * +_thread_tag_storage(void **tag, void *storage, size_t sz, void *err) +{ + struct _thread_tag *tt; + void *ret; + + if (*tag == NULL) + _thread_tag_init(tag); + tt = *tag; + + ret = pthread_getspecific(tt->k); + if (ret == NULL) { + ret = malloc(sz); + if (ret == NULL) + ret = err; + else { + if (pthread_setspecific(tt->k, ret) == 0) + memcpy(ret, storage, sz); + else { + free(ret); + ret = err; + } + } + } + return ret; +} |