1 /* pthread_key_create. Hurd version. 2 Copyright (C) 2002-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #include <pthread.h> 20 #include <stdlib.h> 21 #include <assert.h> 22 23 #include <pt-internal.h> 24 #include <pthreadP.h> 25 26 pthread_mutex_t __pthread_key_lock; 27 pthread_once_t __pthread_key_once = PTHREAD_ONCE_INIT; 28 29 void (**__pthread_key_destructors) (void *arg); 30 int __pthread_key_size; 31 int __pthread_key_count; 32 int __pthread_key_invalid_count; 33 34 int __pthread_key_create(pthread_key_t * key,void (* destructor)(void *))35__pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) 36 { 37 /* Where to look for the next key slot. */ 38 static int index; 39 40 __pthread_key_lock_ready (); 41 42 __pthread_mutex_lock (&__pthread_key_lock); 43 44 do_search: 45 /* Use the search hint and try to find a free slot. */ 46 for (; index < __pthread_key_count 47 && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID; index++) 48 ; 49 50 /* See if we actually found a free element. */ 51 if (index < __pthread_key_count) 52 { 53 assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID); 54 assert (__pthread_key_invalid_count > 0); 55 56 __pthread_key_invalid_count--; 57 __pthread_key_destructors[index] = destructor; 58 *key = index++; 59 60 __pthread_mutex_unlock (&__pthread_key_lock); 61 return 0; 62 } 63 64 assert (index == __pthread_key_count); 65 66 /* No space at the end. */ 67 if (__pthread_key_size == __pthread_key_count) 68 { 69 /* See if it is worth looking for a free element. */ 70 if (__pthread_key_invalid_count > 4 71 && __pthread_key_invalid_count > __pthread_key_size / 8) 72 { 73 index = 0; 74 goto do_search; 75 } 76 77 78 /* Resize the array. */ 79 { 80 void *t; 81 int newsize; 82 83 if (__pthread_key_size == 0) 84 newsize = 8; 85 else 86 newsize = __pthread_key_size * 2; 87 88 t = realloc (__pthread_key_destructors, 89 newsize * sizeof (*__pthread_key_destructors)); 90 if (t == NULL) 91 { 92 __pthread_mutex_unlock (&__pthread_key_lock); 93 return ENOMEM; 94 } 95 96 __pthread_key_size = newsize; 97 __pthread_key_destructors = t; 98 } 99 } 100 101 __pthread_key_destructors[index] = destructor; 102 *key = index; 103 104 index++; 105 __pthread_key_count++; 106 107 __pthread_mutex_unlock (&__pthread_key_lock); 108 return 0; 109 } 110 weak_alias (__pthread_key_create, pthread_key_create) 111 hidden_def (__pthread_key_create) 112