X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/5b2abdfbf4211b6592cdd02b9507555a0ecbb04b..1f2f436a38f7ae2d39a943ad2898d8fed4ed2e58:/pthreads/pthread_tsd.c diff --git a/pthreads/pthread_tsd.c b/pthreads/pthread_tsd.c index f8cfb6b..070fc2d 100644 --- a/pthreads/pthread_tsd.c +++ b/pthreads/pthread_tsd.c @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2000-2003, 2007 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ /* * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 * All Rights Reserved @@ -26,6 +48,7 @@ /* * POSIX Pthread Library * Thread Specific Data support + * NB: pthread_getspecific() is in a separate assembly file */ #include "pthread_internals.h" @@ -34,9 +57,27 @@ static struct { int created; /* Set TRUE if 'create_key' used this slot */ void (*destructor)(void *); -} _pthread_keys[_POSIX_THREAD_KEYS_MAX]; +} _pthread_keys[_INTERNAL_POSIX_THREAD_KEYS_END]; static pthread_lock_t tds_lock = LOCK_INITIALIZER; +/* + * Partition _pthread_keys in a lower part that dyld can use, and an upper + * part for libSystem. The libSystem part starts at __pthread_tsd_first = 4. + * dyld will set this value to 1. + * LEFT OVER TILL DYLD changes to using static (1-3) numbers + */ + +#ifdef DYLD_STATIC_LIBC_BUILD +__private_extern__ int __pthread_tsd_first = 1; +__private_extern__ int __pthread_tsd_start = 5; +__private_extern__ int __pthread_tsd_end = 10; +__private_extern__ int __pthread_tsd_max = 10; +#else +__private_extern__ int __pthread_tsd_first = 10; +__private_extern__ int __pthread_tsd_start = _INTERNAL_POSIX_THREAD_KEYS_MAX; +__private_extern__ int __pthread_tsd_end = _INTERNAL_POSIX_THREAD_KEYS_END; +__private_extern__ int __pthread_tsd_max = 10; +#endif /* * Create a new key for thread specific data */ @@ -46,15 +87,16 @@ pthread_key_create(pthread_key_t *key, { int res, i; LOCK(tds_lock); - res = ENOMEM; /* No 'free' keys */ - for (i = 0; i < _POSIX_THREAD_KEYS_MAX; i++) + res = EAGAIN; /* No 'free' keys, return EAGAIN (as per standard) */ + /* The first slot is reserved for pthread_self() */ + for (i = __pthread_tsd_start; i < __pthread_tsd_end; i++) { if (_pthread_keys[i].created == FALSE) { _pthread_keys[i].created = TRUE; _pthread_keys[i].destructor = destructor; - *key = i+1; - res = ESUCCESS; + *key = i; + res = 0; break; } } @@ -70,12 +112,21 @@ pthread_key_delete(pthread_key_t key) { int res; LOCK(tds_lock); - if ((key >= 1) && (key <= _POSIX_THREAD_KEYS_MAX)) + /* The first slot is reserved for pthread_self() */ + if ((key >= __pthread_tsd_start) && (key < __pthread_tsd_end)) { - if (_pthread_keys[key-1].created) + if (_pthread_keys[key].created) { - _pthread_keys[key-1].created = FALSE; - res = ESUCCESS; + struct _pthread * p; + + _pthread_keys[key].created = FALSE; + LOCK(_pthread_list_lock); + TAILQ_FOREACH(p, &__pthread_head, plist) { + /* It is an 32bit value no lock needed */ + p->tsd[key] = 0; + } + UNLOCK(_pthread_list_lock); + res = 0; } else { res = EINVAL; @@ -103,13 +154,19 @@ pthread_setspecific(pthread_key_t key, { int res; pthread_t self; - if ((key >= 1) && (key <= _POSIX_THREAD_KEYS_MAX)) + /* The first slot is reserved for pthread_self() */ + if ((key >= __pthread_tsd_first) && (key < __pthread_tsd_end)) { - if (_pthread_keys[key-1].created) + if ((key < __pthread_tsd_start) || _pthread_keys[key].created) { self = pthread_self(); - self->tsd[key-1] = (void *) value; - res = ESUCCESS; + self->tsd[key] = (void *) value; + res = 0; + if ((key < __pthread_tsd_start) && (_pthread_keys[key].created == FALSE)) + _pthread_keys[key].created = TRUE; + + if (key > self->max_tsd_key) + self->max_tsd_key = key; } else { res = EINVAL; @@ -121,27 +178,6 @@ pthread_setspecific(pthread_key_t key, return (res); } -/* - * Fetch the thread private value for a given key. - * This is potentially a very heavily-used operation so we do only - * a minimum of checks. - */ -void * -pthread_getspecific(pthread_key_t key) -{ - pthread_t self; - void *res; - if ((key >= 1) && (key <= _POSIX_THREAD_KEYS_MAX)) - { - self = pthread_self(); - res = self->tsd[key-1]; - } else - { /* Invalid key - no error, just NULL */ - res = (void *)NULL; - } - return (res); -} - /* * Clean up thread specific data as thread 'dies' */ @@ -150,9 +186,31 @@ _pthread_tsd_cleanup(pthread_t self) { int i, j; void *param; + + /* destroy dynamic keys first */ for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) { - for (i = 0; i < _POSIX_THREAD_KEYS_MAX; i++) + for (i = __pthread_tsd_start; i <= self->max_tsd_key; i++) + { + if (_pthread_keys[i].created && (param = self->tsd[i])) + { + self->tsd[i] = (void *)NULL; + if (_pthread_keys[i].destructor) + { + (_pthread_keys[i].destructor)(param); + } + } + } + } + + self->max_tsd_key = 0; + + /* + * The first slot is reserved for pthread_self() and there is no cleanup on it. + * Destroy rest of the static keys next only if any destructors registered. + */ + for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) { + for (i = __pthread_tsd_first; i <= __pthread_tsd_max; i++) { if (_pthread_keys[i].created && (param = self->tsd[i])) { @@ -165,3 +223,32 @@ _pthread_tsd_cleanup(pthread_t self) } } } + +int +pthread_key_init_np(int key, void (*destructor)(void *)) +{ + if ((key >= __pthread_tsd_first) && (key < __pthread_tsd_start)) { + LOCK(tds_lock); + _pthread_keys[key].created = TRUE; + _pthread_keys[key].destructor = destructor; + + if (key > __pthread_tsd_max) + __pthread_tsd_max = key; + UNLOCK(tds_lock); + return (0); + } else + return(EINVAL); +} + +/* we need this till the switchover happens for the dyld. It get 1- 10 slot */ +void +_pthread_keys_init() +{ + if (__pthread_tsd_first == 1) { + __pthread_tsd_start = 5; + __pthread_tsd_end = 10; + __pthread_tsd_max = 10; + } + +} +