diff options
| author | rpj <rpj> | 1998-12-22 15:59:24 +0000 | 
|---|---|---|
| committer | rpj <rpj> | 1998-12-22 15:59:24 +0000 | 
| commit | 95aa0a376d93ee021a6c085c71418e9f16513e0a (patch) | |
| tree | f05f436e30d759df3af5cfe9e2cde62e3efa6f1b /tsd.c | |
| parent | 4650bcf1f1efd88a0c8f502c28945bfabd7ef6db (diff) | |
Sun Dec 20 14:51:58 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au>
        * 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  <rpj@ixobrychus.canberra.edu.au>
        * 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  <rpj@ixobrychus.canberra.edu.au>
        * 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.
Diffstat (limited to 'tsd.c')
| -rw-r--r-- | tsd.c | 307 | 
1 files changed, 307 insertions, 0 deletions
| @@ -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 <JEB>. + */ + +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)); +} + +/* </JEB> */ + + +#if 0 /* Pre Bossom */ +  #include <errno.h>  #include "pthread.h" @@ -204,3 +510,4 @@ pthread_key_delete(pthread_key_t key)    return ret;  } +#endif /* Pre Bossom */ | 
