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 | |
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 |
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 (ptr: __pthread_key_destructors, |
88 | size: 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 |