summaryrefslogtreecommitdiff
path: root/sysdeps/generic/pt-key-create.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/pt-key-create.c')
-rw-r--r--sysdeps/generic/pt-key-create.c88
1 files changed, 84 insertions, 4 deletions
diff --git a/sysdeps/generic/pt-key-create.c b/sysdeps/generic/pt-key-create.c
index 33f691b..f26ec36 100644
--- a/sysdeps/generic/pt-key-create.c
+++ b/sysdeps/generic/pt-key-create.c
@@ -1,4 +1,4 @@
-/* pthread_key_create. Generic version.
+/* pthread_key_create. Hurd version.
Copyright (C) 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -18,13 +18,93 @@
Boston, MA 02111-1307, USA. */
#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+
#include <pt-internal.h>
+pthread_mutex_t __pthread_key_lock;
+
+void (**__pthread_key_destructors) (void *arg);
+int __pthread_key_size;
+int __pthread_key_count;
+int __pthread_key_invalid_count;
+
int
__pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
{
- return ENOSYS;
-}
+ /* Where to look for the next key slot. */
+ static int index;
+
+ __pthread_key_lock_ready ();
+
+ __pthread_mutex_lock (&__pthread_key_lock);
+
+ do_search:
+ /* Use the search hint and try to find a free slot. */
+ for (; index < __pthread_key_count
+ && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID;
+ index ++)
+ ;
+
+ /* See if we actually found a free element. */
+ if (index < __pthread_key_count)
+ {
+ assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID);
+ assert (__pthread_key_invalid_count > 0);
+
+ __pthread_key_invalid_count --;
+ __pthread_key_destructors[index] = destructor;
+ *key = index ++;
+
+ __pthread_mutex_unlock (&__pthread_key_lock);
+ return 0;
+ }
+ assert (index == __pthread_key_count);
+
+ /* No space at the end. */
+ if (__pthread_key_size == __pthread_key_count)
+ {
+ /* See if it is worth looking for a free element. */
+ if (__pthread_key_invalid_count > 4
+ && __pthread_key_invalid_count > __pthread_key_size / 8)
+ {
+ index = 0;
+ goto do_search;
+ }
+
+
+ /* Resize the array. */
+ {
+ void *t;
+ int newsize;
+
+ if (__pthread_key_size == 0)
+ newsize = 8;
+ else
+ newsize = __pthread_key_size * 2;
+
+ t = realloc (__pthread_key_destructors,
+ newsize * sizeof (*__pthread_key_destructors));
+ if (! t)
+ {
+ __pthread_mutex_unlock (&__pthread_key_lock);
+ return ENOMEM;
+ }
+
+ __pthread_key_size = newsize;
+ __pthread_key_destructors = t;
+ }
+ }
+
+ __pthread_key_destructors[index] = destructor;
+ *key = index;
+
+ index ++;
+ __pthread_key_count ++;
+
+ __pthread_mutex_unlock (&__pthread_key_lock);
+ return 0;
+}
strong_alias (__pthread_key_create, pthread_key_create)
-stub_warning (pthread_key_create)