diff options
Diffstat (limited to 'sysdeps/generic/pt-key-create.c')
-rw-r--r-- | sysdeps/generic/pt-key-create.c | 88 |
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) |