summaryrefslogtreecommitdiff
path: root/lib/librthread/rthread_libc.c
diff options
context:
space:
mode:
authorMarco S Hyman <marc@cvs.openbsd.org>2006-01-05 04:06:49 +0000
committerMarco S Hyman <marc@cvs.openbsd.org>2006-01-05 04:06:49 +0000
commita1d0ddad6a3714e2f9848d55f7bf68bfc73087b6 (patch)
tree2bd741fc5dd562800ac0ccfc38fc52ac138b89b1 /lib/librthread/rthread_libc.c
parent4f2f633593bcff3fc73430c2375dff9f1eafb9fa (diff)
add -Wstrict-prototypes -Wmissing-prototypes -Wsign-compare
Minor tweaks to compile with the above, primarily in fixing the conflicts between semaphore.h and rthread.h "i like the additional warnings" tedu@
Diffstat (limited to 'lib/librthread/rthread_libc.c')
-rw-r--r--lib/librthread/rthread_libc.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/lib/librthread/rthread_libc.c b/lib/librthread/rthread_libc.c
new file mode 100644
index 00000000000..d50a1e09d08
--- /dev/null
+++ b/lib/librthread/rthread_libc.c
@@ -0,0 +1,127 @@
+/* $OpenBSD: rthread_libc.c,v 1.1 2006/01/05 04:06:48 marc Exp $ */
+/* $snafu: libc_tag.c,v 1.4 2004/11/30 07:00:06 marc Exp $ */
+
+/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
+
+#define _POSIX_THREADS
+
+#include <sys/time.h>
+
+#include <machine/spinlock.h>
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "thread_private.h" /* in libc/include */
+
+#include "rthread.h"
+
+/*
+ * A thread tag is a pointer to a structure of this type. 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)
+ _rthread_debug(1, "tag init failure");
+}
+
+/*
+ * 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)
+ _rthread_debug(1, "tag mutex lock failure");
+ }
+}
+
+/*
+ * 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)
+ _rthread_debug(1, "tag mutex unlock failure");
+ }
+}
+
+/*
+ * 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;
+}