]> git.saurik.com Git - apple/libc.git/blame - pthreads/pthread_tsd.c
Libc-320.1.3.tar.gz
[apple/libc.git] / pthreads / pthread_tsd.c
CommitLineData
9385eb3d
A
1/*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
9385eb3d
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
e9ce8d39
A
23/*
24 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
25 * All Rights Reserved
26 *
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby granted,
29 * provided that the above copyright notice appears in all copies and
30 * that both the copyright notice and this permission notice appear in
31 * supporting documentation.
32 *
33 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
36 *
37 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42 *
43 */
44/*
45 * MkLinux
46 */
47
48/*
49 * POSIX Pthread Library
50 * Thread Specific Data support
9385eb3d 51 * NB: pthread_getspecific() is in a separate assembly file
e9ce8d39
A
52 */
53
54#include "pthread_internals.h"
55
56static struct
57{
58 int created; /* Set TRUE if 'create_key' used this slot */
59 void (*destructor)(void *);
60} _pthread_keys[_POSIX_THREAD_KEYS_MAX];
61static pthread_lock_t tds_lock = LOCK_INITIALIZER;
62
63/*
64 * Create a new key for thread specific data
65 */
66int
67pthread_key_create(pthread_key_t *key,
68 void (*destructor)(void *))
69{
70 int res, i;
71 LOCK(tds_lock);
72 res = ENOMEM; /* No 'free' keys */
9385eb3d
A
73 /* The first slot is reserved for pthread_self() */
74 for (i = 1; i < _POSIX_THREAD_KEYS_MAX; i++)
e9ce8d39
A
75 {
76 if (_pthread_keys[i].created == FALSE)
77 {
78 _pthread_keys[i].created = TRUE;
79 _pthread_keys[i].destructor = destructor;
9385eb3d 80 *key = i;
e9ce8d39
A
81 res = ESUCCESS;
82 break;
83 }
84 }
85 UNLOCK(tds_lock);
86 return (res);
87}
88
89/*
90 * Destroy a thread specific data key
91 */
92int
93pthread_key_delete(pthread_key_t key)
94{
95 int res;
96 LOCK(tds_lock);
9385eb3d
A
97 /* The first slot is reserved for pthread_self() */
98 if ((key > 0) && (key < _POSIX_THREAD_KEYS_MAX))
e9ce8d39 99 {
9385eb3d 100 if (_pthread_keys[key].created)
e9ce8d39 101 {
9385eb3d
A
102 struct _pthread * p;
103
104 _pthread_keys[key].created = FALSE;
105 LOCK(_pthread_list_lock);
106 LIST_FOREACH(p, &__pthread_head, plist) {
107 /* It is an 32bit value no lock needed */
108 p->tsd[key] = 0;
109 }
110 UNLOCK(_pthread_list_lock);
e9ce8d39
A
111 res = ESUCCESS;
112 } else
113 {
114 res = EINVAL;
115 }
116 } else
117 { /* Invalid key */
118 res = EINVAL;
119 }
120 UNLOCK(tds_lock);
121 return (res);
122}
123
124/*
125 * Set the thread private value for a given key.
126 * We do not take the spinlock for this or pthread_getspecific.
127 * The assignment to self->tsd[] is thread-safe because we never
128 * refer to the tsd[] of a thread other than pthread_self().
129 * The reference to _pthread_keys[...].created could race with a
130 * pthread_key_delete() but in this case the behaviour is allowed
131 * to be undefined.
132 */
133int
134pthread_setspecific(pthread_key_t key,
135 const void *value)
136{
137 int res;
138 pthread_t self;
9385eb3d
A
139 /* The first slot is reserved for pthread_self() */
140 if ((key > 0) && (key < _POSIX_THREAD_KEYS_MAX))
e9ce8d39 141 {
9385eb3d 142 if (_pthread_keys[key].created)
e9ce8d39
A
143 {
144 self = pthread_self();
9385eb3d 145 self->tsd[key] = (void *) value;
e9ce8d39
A
146 res = ESUCCESS;
147 } else
148 {
149 res = EINVAL;
150 }
151 } else
152 { /* Invalid key */
153 res = EINVAL;
154 }
155 return (res);
156}
157
e9ce8d39
A
158/*
159 * Clean up thread specific data as thread 'dies'
160 */
161void
162_pthread_tsd_cleanup(pthread_t self)
163{
164 int i, j;
165 void *param;
166 for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
167 {
9385eb3d
A
168 /* The first slot is reserved for pthread_self() */
169 for (i = 1; i < _POSIX_THREAD_KEYS_MAX; i++)
e9ce8d39
A
170 {
171 if (_pthread_keys[i].created && (param = self->tsd[i]))
172 {
173 self->tsd[i] = (void *)NULL;
174 if (_pthread_keys[i].destructor)
175 {
176 (_pthread_keys[i].destructor)(param);
177 }
178 }
179 }
180 }
181}