2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/lib/libc_r/uthread/uthread_spec.c,v 1.14.2.2 2002/10/22 14:44:03 fjoe Exp $
33 * $DragonFly: src/lib/libc_r/uthread/uthread_spec.c,v 1.3 2005/05/30 20:50:53 joerg Exp $
40 #include "pthread_private.h"
42 /* Static variables: */
43 static struct pthread_key key_table
[PTHREAD_KEYS_MAX
];
46 _pthread_key_create(pthread_key_t
* key
, void (*destructor
) (void *))
48 for ((*key
) = 0; (*key
) < PTHREAD_KEYS_MAX
; (*key
)++) {
49 /* Lock the key table entry: */
50 _SPINLOCK(&key_table
[*key
].lock
);
52 if (key_table
[(*key
)].allocated
== 0) {
53 key_table
[(*key
)].allocated
= 1;
54 key_table
[(*key
)].destructor
= destructor
;
56 /* Unlock the key table entry: */
57 _SPINUNLOCK(&key_table
[*key
].lock
);
61 /* Unlock the key table entry: */
62 _SPINUNLOCK(&key_table
[*key
].lock
);
68 _pthread_key_delete(pthread_key_t key
)
72 if (key
< PTHREAD_KEYS_MAX
) {
73 /* Lock the key table entry: */
74 _SPINLOCK(&key_table
[key
].lock
);
76 if (key_table
[key
].allocated
)
77 key_table
[key
].allocated
= 0;
81 /* Unlock the key table entry: */
82 _SPINUNLOCK(&key_table
[key
].lock
);
89 _thread_cleanupspecific(void)
91 struct pthread
*curthread
= _get_curthread();
95 void (*destructor
)( void *);
97 for (itr
= 0; itr
< PTHREAD_DESTRUCTOR_ITERATIONS
; itr
++) {
98 for (key
= 0; key
< PTHREAD_KEYS_MAX
; key
++) {
99 if (curthread
->specific_data_count
) {
100 /* Lock the key table entry: */
101 _SPINLOCK(&key_table
[key
].lock
);
104 if (key_table
[key
].allocated
) {
105 if (curthread
->specific_data
[key
]) {
106 data
= (void *) curthread
->specific_data
[key
];
107 curthread
->specific_data
[key
] = NULL
;
108 curthread
->specific_data_count
--;
109 destructor
= key_table
[key
].destructor
;
113 /* Unlock the key table entry: */
114 _SPINUNLOCK(&key_table
[key
].lock
);
117 * If there is a destructore, call it
118 * with the key table entry unlocked:
123 free(curthread
->specific_data
);
124 curthread
->specific_data
= NULL
;
129 free(curthread
->specific_data
);
130 curthread
->specific_data
= NULL
;
133 static inline const void **
134 pthread_key_allocate_data(void)
136 const void **new_data
;
137 if ((new_data
= (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX
)) != NULL
) {
138 memset((void *) new_data
, 0, sizeof(void *) * PTHREAD_KEYS_MAX
);
144 _pthread_setspecific(pthread_key_t key
, const void *value
)
146 struct pthread
*pthread
;
149 /* Point to the running thread: */
150 pthread
= _get_curthread();
152 if ((pthread
->specific_data
) ||
153 (pthread
->specific_data
= pthread_key_allocate_data())) {
154 if (key
< PTHREAD_KEYS_MAX
) {
155 if (key_table
[key
].allocated
) {
156 if (pthread
->specific_data
[key
] == NULL
) {
158 pthread
->specific_data_count
++;
161 pthread
->specific_data_count
--;
163 pthread
->specific_data
[key
] = value
;
175 _pthread_getspecific(pthread_key_t key
)
177 struct pthread
*pthread
;
180 /* Point to the running thread: */
181 pthread
= _get_curthread();
183 /* Check if there is specific data: */
184 if (pthread
->specific_data
!= NULL
&& key
< PTHREAD_KEYS_MAX
) {
185 /* Check if this key has been used before: */
186 if (key_table
[key
].allocated
) {
187 /* Return the value: */
188 data
= (void *) pthread
->specific_data
[key
];
191 * This key has not been used before, so return NULL
197 /* No specific data has been created, so just return NULL: */
202 __strong_reference(_pthread_key_create
, pthread_key_create
);
203 __strong_reference(_pthread_key_delete
, pthread_key_delete
);
204 __strong_reference(_pthread_getspecific
, pthread_getspecific
);
205 __strong_reference(_pthread_setspecific
, pthread_setspecific
);