summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/thread
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/thread')
-rw-r--r--lib/libpthread/thread/Makefile.inc4
-rw-r--r--lib/libpthread/thread/thread_storage.c82
-rw-r--r--lib/libpthread/thread/thread_tag.c120
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;
+}