diff options
author | David Leonard <d@cvs.openbsd.org> | 2000-01-06 07:25:16 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 2000-01-06 07:25:16 +0000 |
commit | 58ca2ba3d7b23e0a7d454dcbad7fcf720b1880cb (patch) | |
tree | 107943a0352e10864c6d8d3e06344849de245009 /lib | |
parent | aa15e0fdc87c0d8c0b06d252425b1e5125f31209 (diff) |
thread-specific storage helper
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc_r/thread/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libc_r/thread/thread_storage.c | 77 | ||||
-rw-r--r-- | lib/libpthread/thread/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libpthread/thread/thread_storage.c | 77 |
4 files changed, 164 insertions, 0 deletions
diff --git a/lib/libc_r/thread/Makefile.inc b/lib/libc_r/thread/Makefile.inc new file mode 100644 index 00000000000..919300d08ae --- /dev/null +++ b/lib/libc_r/thread/Makefile.inc @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile.inc,v 1.1 2000/01/06 07:25:15 d Exp $ + +.PATH: ${LIBC_RSRCDIR}/thread + +SRCS+= thread_storage.c diff --git a/lib/libc_r/thread/thread_storage.c b/lib/libc_r/thread/thread_storage.c new file mode 100644 index 00000000000..7d4012ecb35 --- /dev/null +++ b/lib/libc_r/thread/thread_storage.c @@ -0,0 +1,77 @@ + +/* libpthread's stronger functions */ + +#include <stdlib.h> +#include <pthread.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) __P((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/Makefile.inc b/lib/libpthread/thread/Makefile.inc new file mode 100644 index 00000000000..919300d08ae --- /dev/null +++ b/lib/libpthread/thread/Makefile.inc @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile.inc,v 1.1 2000/01/06 07:25:15 d Exp $ + +.PATH: ${LIBC_RSRCDIR}/thread + +SRCS+= thread_storage.c diff --git a/lib/libpthread/thread/thread_storage.c b/lib/libpthread/thread/thread_storage.c new file mode 100644 index 00000000000..7d4012ecb35 --- /dev/null +++ b/lib/libpthread/thread/thread_storage.c @@ -0,0 +1,77 @@ + +/* libpthread's stronger functions */ + +#include <stdlib.h> +#include <pthread.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) __P((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; +} |