From 95aa0a376d93ee021a6c085c71418e9f16513e0a Mon Sep 17 00:00:00 2001 From: rpj Date: Tue, 22 Dec 1998 15:59:24 +0000 Subject: Sun Dec 20 14:51:58 1998 Ross Johnson * misc.c (pthreadCancelableWait): New function by John Bossom. Non-stand ard but provides a hook that can be used to implement cancellation points in applications that use this library. * pthread.h (pthread_cleanup_pop): C++ (non-WIN32) version uses try/catch to emulate John Bossom's WIN32 __try/__finally behaviour. In the WIN32 version __finally block, add a test for AbnormalTermination otherwise cleanup is only run if the cleanup_pop execute arg is non-zero. Cancella tion should cause the cleanup to run irrespective of the execute arg. * condvar.c (pthread_condattr_init): Replaced by John Bossom's version. (pthread_condattr_destroy): Replaced by John Bossom's version. (pthread_condattr_getpshared): Replaced by John Bossom's version. (pthread_condattr_setpshared): Replaced by John Bossom's version. (pthread_cond_init): Replaced by John Bossom's version. Fix comment (refered to mutex rather than condition variable). (pthread_cond_destroy): Replaced by John Bossom's version. (pthread_cond_wait): Replaced by John Bossom's version. (pthread_cond_timedwait): Replaced by John Bossom's version. (pthread_cond_signal): Replaced by John Bossom's version. (pthread_cond_broadcast): Replaced by John Bossom's version. Thu Dec 17 19:10:46 1998 Ross Johnson * tsd.c (pthread_key_create): Replaced by John Bossom's version. (pthread_key_delete): Replaced by John Bossom's version. (pthread_setspecific): Replaced by John Bossom's version. (pthread_getspecific): Replaced by John Bossom's version. Mon Dec 7 09:44:40 1998 Ross Johnson * cancel.c (pthread_setcancelstate): Replaced by John Bossom's version. (pthread_setcanceltype): Replaced by John Bossom's version. (pthread_testcancel): Replaced by John Bossom's version. (pthread_cancel): Replaced by John Bossom's version. * exit.c (pthread_exit): Replaced by John Bossom's version. * misc.c (pthread_self): Replaced by John Bossom's version. (pthread_equal): Replaced by John Bossom's version. * sync.c (pthread_detach): Replaced by John Bossom's version. (pthread_join): Replaced by John Bossom's version. * create.c (pthread_create): Replaced by John Bossom's version. * private.c (_pthread_processInitialize): New by John Bossom. (_pthread_processTerminate): Non-public function by John Bossom. (_pthread_threadStart): Non-public function by John Bossom. (_pthread_threadDestroy): Non-public function by John Bossom. (_pthread_cleanupStack): Non-public function by John Bossom. (_pthread_tkAssocCreate): Non-public function by John Bossom. (_pthread_tkAssocDestroy): Non-public function by John Bossom. (_pthread_callUserDestroyRoutines): Non-public function by John Bossom. * implement.h: Added John Bossom's non-API structures and declarations. * dll.c (PthreadsEntryPoint): Cast return value of GetProcAddress to resolve compile warning from MSVC. * dll.c (DLLmain): Replaced by John Bossom's version. * dll.c (PthreadsEntryPoint): Re-applied Anders Norlander's patch:- Initialize _pthread_try_enter_critical_section at startup and release kernel32 handle when DLL is being unloaded. --- tsd.c | 307 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) (limited to 'tsd.c') diff --git a/tsd.c b/tsd.c index cc0b98e..757ea9f 100644 --- a/tsd.c +++ b/tsd.c @@ -48,6 +48,312 @@ * One more thing to note: destructors must never be called on deleted keys. */ +#include "pthread.h" +#include "implement.h" + +/* + * Code contributed by John E. Bossom . + */ + +int +pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function creates a thread-specific data key visible + * to all threads. All existing and new threads have a value + * NULL for key until set using pthread_setspecific. When any + * thread with a non-NULL value for key terminates, 'destructor' + * is called with key's current value for that thread. + * + * PARAMETERS + * key + * pointer to an instance of pthread_key_t + * + * + * DESCRIPTION + * This function creates a thread-specific data key visible + * to all threads. All existing and new threads have a value + * NULL for key until set using pthread_setspecific. When any + * thread with a non-NULL value for key terminates, 'destructor' + * is called with key's current value for that thread. + * + * RESULTS + * 0 successfully created semaphore, + * EAGAIN insufficient resources or PTHREAD_KEYS_MAX + * exceeded, + * ENOMEM insufficient memory to create the key, + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if ((*key = (pthread_key_t) calloc (1, sizeof (**key))) == NULL) + { + result = ENOMEM; + } + else if (((*key)->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES) + { + /* + * Create system key + */ + result = EAGAIN; + + free (*key); + *key = NULL; + } + else if (destructor != NULL) + { + /* + * Have to manage associations between thread and key; + * Therefore, need a lock that allows multiple threads + * to gain exclusive access to the key->threads list + */ + result = pthread_mutex_init (&((*key)->threadsLock), NULL); + + if (result != 0) + { + TlsFree ((*key)->key); + + free (*key); + *key = NULL; + } + (*key)->destructor = destructor; + } + + return (result); +} + +int +pthread_key_delete (pthread_key_t key) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function deletes a thread-specific data key. This + * does not change the value of the thread spcific data key + * for any thread and does not run the key's destructor + * in any thread so it should be used with caution. + * + * PARAMETERS + * key + * pointer to an instance of pthread_key_t + * + * + * DESCRIPTION + * This function deletes a thread-specific data key. This + * does not change the value of the thread spcific data key + * for any thread and does not run the key's destructor + * in any thread so it should be used with caution. + * + * RESULTS + * 0 successfully deleted the key, + * EINVAL key is invalid, + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if (key != NULL) + { + if (key->threads != NULL && + pthread_mutex_lock (&(key->threadsLock)) == 0) + { + /* + * Run through all Thread<-->Key associations + * for this key. + * If the pthread_t still exits (ie the assoc->thread + * is not NULL) then leave the assoc for the thread to + * destroy. + * Notes: + * If assoc->thread is NULL, then the associated thread + * is no longer referencing this assoc. + * The association is only referenced + * by this key and must be released; otherwise + * the assoc will be destroyed when the thread is destroyed. + */ + ThreadKeyAssoc *assoc; + + assoc = (ThreadKeyAssoc *) key->threads; + + while (assoc != NULL) + { + if (pthread_mutex_lock (&(assoc->lock)) == 0) + { + ThreadKeyAssoc *next; + + assoc->key = NULL; + next = assoc->nextThread; + assoc->nextThread = NULL; + + pthread_mutex_unlock (&(assoc->lock)); + + tkAssocDestroy (assoc); + + assoc = next; + } + } + pthread_mutex_unlock (&(key->threadsLock)); + } + + TlsFree (key->key); + if (key->destructor != NULL) + { + pthread_mutex_destroy (&(key->threadsLock)); + } + +#if defined( _DEBUG ) + memset ((char *) key, 0, sizeof (*key)); +#endif + free (key); + } + + return (result); +} + + +int +pthread_setspecific (pthread_key_t key, const void *value) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function initializes an unnamed semaphore. the + * initial value of the semaphore is 'value' + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * + * DESCRIPTION + * This function initializes an unnamed semaphore. The + * initial value of the semaphore is set to 'value'. + * + * RESULTS + * 0 successfully created semaphore, + * EINVAL 'sem' is not a valid semaphore, + * ENOSPC a required resource has been exhausted, + * ENOSYS semaphores are not supported, + * EPERM the process lacks appropriate privilege + * + * ------------------------------------------------------ + */ +{ + pthread_t self; + int result = 0; + + if (key != _pthread_selfThreadKey) + { + /* + * Using pthread_self will implicitly create + * an instance of pthread_t for the current + * thread if one wasn't explicitly created + */ + self = pthread_self (); + } + else + { + /* + * Resolve catch-22 of registering thread with threadSelf + * key + */ + self = pthread_getspecific (_pthread_selfThreadKey); + if (self == NULL) + { + self = (pthread_t) value; + } + } + + result = 0; + + if (key != NULL) + { + ThreadKeyAssoc *assoc; + + if (self != NULL && + key->destructor != NULL && + value != NULL) + { + /* + * Only require associations if we have to + * call user destroy routine. + * Don't need to locate an existing association + * when setting data to NULL for WIN32 since the + * data is stored with the operating system; not + * on the association; setting assoc to NULL short + * circuits the search. + */ + assoc = (ThreadKeyAssoc *) self->keys; + /* + * Locate existing association + */ + while (assoc != NULL) + { + if (assoc->key == key) + { + /* + * Association already exists + */ + break; + } + assoc = assoc->nextKey; + } + + /* + * create an association if not found + */ + result = (assoc == NULL) + ? tkAssocCreate (&assoc, self, key) + : 0; + } + else + { + result = 0; + } + + if (result == 0) + { + TlsSetValue (key->key, (LPVOID) value); + } + } + return (result); +} /* pthread_setspecific */ + + +void * +pthread_getspecific (pthread_key_t key) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function returns the current value of key in the + * calling thread. If no value has been set for 'key' in + * the thread, NULL is returned. + * + * PARAMETERS + * key + * an instance of pthread_key_t + * + * + * DESCRIPTION + * This function returns the current value of key in the + * calling thread. If no value has been set for 'key' in + * the thread, NULL is returned. + * + * RESULTS + * key value + * + * ------------------------------------------------------ + */ +{ + return (TlsGetValue (key->key)); +} + +/* */ + + +#if 0 /* Pre Bossom */ + #include #include "pthread.h" @@ -204,3 +510,4 @@ pthread_key_delete(pthread_key_t key) return ret; } +#endif /* Pre Bossom */ -- cgit v1.2.3