summaryrefslogtreecommitdiff
path: root/libthreads/cthread_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'libthreads/cthread_data.c')
-rw-r--r--libthreads/cthread_data.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/libthreads/cthread_data.c b/libthreads/cthread_data.c
new file mode 100644
index 00000000..0814130d
--- /dev/null
+++ b/libthreads/cthread_data.c
@@ -0,0 +1,188 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991 Carnegie-Mellon University
+ * All rights reserved. The CMU software License Agreement specifies
+ * the terms and conditions for use and redistribution.
+ */
+/*
+ * HISTORY
+ * $Log: cthread_data.c,v $
+ * Revision 2.2 92/05/23 11:35:17 jfriedl
+ * Snarfed from multi-server sources at CMU.
+ * No stdio (for use with single-server).
+ *
+ *
+ * Revision 2.2 91/03/25 14:14:45 jjc
+ * For compatibility with cthread_data:
+ * 1) Added routines, cthread_data and cthread_set_data,
+ * which use the new routines in here.
+ * 2) Defined CTHREAD_KEY_RESERVED as the key used to
+ * access cthread_data.
+ * 3) Changed the first free key from CTHREAD_KEY_NULL
+ * to CTHREAD_KEY_FIRST.
+ * [91/03/18 jjc]
+ * Made simple implementation from POSIX threads specification for
+ * thread specific data.
+ * [91/03/07 jjc]
+ *
+ */
+#include <cthreads.h>
+
+
+#ifdef CTHREAD_DATA
+#define CTHREAD_KEY_FIRST (cthread_key_t)1 /* first free key */
+#else CTHREAD_DATA
+#define CTHREAD_KEY_FIRST CTHREAD_KEY_NULL /* first free key */
+#endif CTHREAD_DATA
+#define CTHREAD_KEY_MAX (cthread_key_t)8 /* max. no. of keys */
+#define CTHREAD_KEY_NULL (cthread_key_t)0
+
+#ifdef CTHREAD_DATA
+/*
+ * Key reserved for cthread_data
+ */
+#define CTHREAD_KEY_RESERVED CTHREAD_KEY_NULL
+#endif CTHREAD_DATA
+
+
+/* lock protecting key creation */
+struct mutex cthread_data_lock = MUTEX_INITIALIZER;
+
+/* next free key */
+cthread_key_t cthread_key = CTHREAD_KEY_FIRST;
+
+
+/*
+ * Create key to private data visible to all threads in task.
+ * Different threads may use same key, but the values bound to the key are
+ * maintained on a thread specific basis.
+ * Returns 0 if successful and returns -1 otherwise.
+ */
+cthread_keycreate(key)
+cthread_key_t *key;
+{
+ if (cthread_key >= CTHREAD_KEY_FIRST && cthread_key < CTHREAD_KEY_MAX) {
+ mutex_lock((mutex_t)&cthread_data_lock);
+ *key = cthread_key++;
+ mutex_unlock((mutex_t)&cthread_data_lock);
+ return(0);
+ }
+ else { /* out of keys */
+ *key = CTHREAD_KEY_INVALID;
+ return(-1);
+ }
+}
+
+
+/*
+ * Get private data associated with given key
+ * Returns 0 if successful and returns -1 if the key is invalid.
+ * If the calling thread doesn't have a value for the given key,
+ * the value returned is CTHREAD_DATA_VALUE_NULL.
+ */
+cthread_getspecific(key, value)
+cthread_key_t key;
+any_t *value;
+{
+ register cthread_t self;
+ register any_t *thread_data;
+
+ *value = CTHREAD_DATA_VALUE_NULL;
+ if (key < CTHREAD_KEY_NULL || key >= cthread_key)
+ return(-1);
+
+ self = cthread_self();
+ thread_data = (any_t *)(self->private_data);
+ if (thread_data != (any_t *)0)
+ *value = thread_data[key];
+
+ return(0);
+}
+
+
+/*
+ * Set private data associated with given key
+ * Returns 0 if successful and returns -1 otherwise.
+ */
+cthread_setspecific(key, value)
+cthread_key_t key;
+any_t value;
+{
+ register int i;
+ register cthread_t self;
+ register any_t *thread_data;
+
+ if (key < CTHREAD_KEY_NULL || key >= cthread_key)
+ return(-1);
+
+ self = cthread_self();
+ thread_data = (any_t *)(self->private_data);
+ if (thread_data != (any_t *)0)
+ thread_data[key] = value;
+ else {
+ /*
+ * Allocate and initialize thread data table,
+ * point cthread_data at it, and then set the
+ * data for the given key with the given value.
+ */
+ thread_data = (any_t *)malloc(CTHREAD_KEY_MAX * sizeof(any_t));
+ if (thread_data == (any_t *)0) {
+ printf("cthread_setspecific: malloc failed\n");
+ return(-1);
+ }
+ self->private_data = (any_t)thread_data;
+
+ for (i = 0; i < CTHREAD_KEY_MAX; i++)
+ thread_data[i] = CTHREAD_DATA_VALUE_NULL;
+
+ thread_data[key] = value;
+ }
+ return(0);
+}
+
+
+#ifdef CTHREAD_DATA
+/*
+ * Set thread specific "global" variable,
+ * using new POSIX routines.
+ * Crash and burn if the thread given isn't the calling thread.
+ * XXX For compatibility with old cthread_set_data() XXX
+ */
+cthread_set_data(t, x)
+cthread_t t;
+any_t x;
+{
+ register cthread_t self;
+
+ self = cthread_self();
+ if (t == self)
+ return(cthread_setspecific(CTHREAD_KEY_RESERVED, x));
+ else {
+ ASSERT(t == self);
+ }
+}
+
+
+/*
+ * Get thread specific "global" variable,
+ * using new POSIX routines.
+ * Crash and burn if the thread given isn't the calling thread.
+ * XXX For compatibility with old cthread_data() XXX
+ */
+any_t
+cthread_data(t)
+cthread_t t;
+{
+ register cthread_t self;
+ any_t value;
+
+ self = cthread_self();
+ if (t == self) {
+ (void)cthread_getspecific(CTHREAD_KEY_RESERVED, &value);
+ return(value);
+ }
+ else {
+ ASSERT(t == self);
+ }
+}
+#endif CTHREAD_DATA