1 /* pthread_key_create. Hurd version. 2 Copyright (C) 2002-2021 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 28 void (**__pthread_key_destructors) (void *arg); 29 int __pthread_key_size; 30 int __pthread_key_count; 31 int __pthread_key_invalid_count; 32 33 int __pthread_key_create(pthread_key_t * key,void (* destructor)(void *))34__pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) 35 { 36 /* Where to look for the next key slot. */ 37 static int index; 38 39 __pthread_key_lock_ready (); 40 41 __pthread_mutex_lock (&__pthread_key_lock); 42 43 do_search: 44 /* Use the search hint and try to find a free slot. */ 45 for (; index < __pthread_key_count 46 && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID; index++) 47 ; 48 49 /* See if we actually found a free element. */ 50 if (index < __pthread_key_count) 51 { 52 assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID); 53 assert (__pthread_key_invalid_count > 0); 54 55 __pthread_key_invalid_count--; 56 __pthread_key_destructors[index] = destructor; 57 *key = index++; 58 59 __pthread_mutex_unlock (&__pthread_key_lock); 60 return 0; 61 } 62 63 assert (index == __pthread_key_count); 64 65 /* No space at the end. */ 66 if (__pthread_key_size == __pthread_key_count) 67 { 68 /* See if it is worth looking for a free element. */ 69 if (__pthread_key_invalid_count > 4 70 && __pthread_key_invalid_count > __pthread_key_size / 8) 71 { 72 index = 0; 73 goto do_search; 74 } 75 76 77 /* Resize the array. */ 78 { 79 void *t; 80 int newsize; 81 82 if (__pthread_key_size == 0) 83 newsize = 8; 84 else 85 newsize = __pthread_key_size * 2; 86 87 t = realloc (__pthread_key_destructors, 88 newsize * sizeof (*__pthread_key_destructors)); 89 if (t == NULL) 90 { 91 __pthread_mutex_unlock (&__pthread_key_lock); 92 return ENOMEM; 93 } 94 95 __pthread_key_size = newsize; 96 __pthread_key_destructors = t; 97 } 98 } 99 100 __pthread_key_destructors[index] = destructor; 101 *key = index; 102 103 index++; 104 __pthread_key_count++; 105 106 __pthread_mutex_unlock (&__pthread_key_lock); 107 return 0; 108 } 109 weak_alias (__pthread_key_create, pthread_key_create) 110 hidden_def (__pthread_key_create) 111