diff options
| -rw-r--r-- | ChangeLog | 41 | ||||
| -rw-r--r-- | cleanup.c | 63 | ||||
| -rw-r--r-- | dll.c | 11 | ||||
| -rw-r--r-- | global.c | 12 | ||||
| -rw-r--r-- | implement.h | 20 | ||||
| -rw-r--r-- | mutex.c | 9 | ||||
| -rw-r--r-- | private.c | 4 | ||||
| -rw-r--r-- | tsd.c | 33 | 
8 files changed, 174 insertions, 19 deletions
@@ -1,3 +1,21 @@ +1998-12-05  Anders Norlander  <anorland@hem2.passagen.se> + +	* implement.h (_pthread_try_enter_critical_section): New extern +	* dll.c (_pthread_try_enter_critical_section): New pointer to +	TryEnterCriticalSection if it exists; otherwise NULL. +	* dll.c (PthreadsEntryPoint): +	Initialize _pthread_try_enter_critical_section at startup +	and release kernel32 handle when DLL is being unloaded. +	* mutex.c (pthread_mutex_trylock): Replaced check for NT with +	a check if _pthread_try_enter_critical_section is valid +	pointer to a function. Call _pthread_try_enter_critical_section +	instead of TryEnterCriticalSection to avoid errors on Win95. + +Sun Nov 15 21:24:06 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> + +	* cleanup.c (_pthread_destructor_run_all): Declare missing void * arg. +	Fixup CVS merge conflicts. +  1998-10-30  Ben Elliston  <bje@cygnus.com>  	* condvar.c (cond_wait): Fix semantic error. Test for equality @@ -11,8 +29,31 @@ Fri Oct 30 15:15:50 1998  Ross Johnson  <rpj@swan.canberra.edu.au>  	(new_thread): Rename poorly named local variable to  	"new_handler". +Sat Oct 24 18:34:59 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> + +	* global.c: Add TSD key management array and index declarations. + +	* implement.h: Ditto for externs. + +Fri Oct 23 00:08:09 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> + +	* implement.h (_PTHREAD_TSD_KEY_REUSE): Add enum. + +	* private.c (_pthread_delete_thread): Add call to +	_pthread_destructor_run_all() to clean up the threads keys. + +	* cleanup.c (_pthread_destructor_run_all): Check for no more dirty +	keys to run destructors on. Assume that the destructor call always +	succeeds and set the key value to NULL. +  Thu Oct 22 21:44:44 1998  Ross Johnson  <rpj@ixobrychus.canberra.edu.au> +	* tsd.c (pthread_setspecific): Add key management code. +	(pthread_key_create): Ditto. +	(pthread_key_delete): Ditto. + +	* implement.h (struct _pthread_tsd_key): Add status member. +  	* tsd.c: Add description of pthread_key_delete() from the  	standard as a comment. @@ -127,6 +127,7 @@ _pthread_destructor_run_all()  {    _pthread_tsd_key_t * key;    int count; +  int dirty;    /* This threads private keys */    key = _pthread_tsd_key_table; @@ -139,24 +140,76 @@ _pthread_destructor_run_all()    for (count = 0; count < PTHREAD_DESTRUCTOR_ITERATIONS; count++)      {        int k; +      void * arg; + +      dirty = 0;        /* Loop through all keys. */        for (k = 0; k < _POSIX_THREAD_KEYS_MAX; k++)  	{ -	  /* If there's no destructor or the key isn't in use, skip it. */ -	  if (key->destructor != NULL && key->in_use == _PTHREAD_TSD_KEY_INUSE) -	    { -	      void * arg; +	  /* CRITICAL SECTION */ +	  pthread_mutex_lock(&_pthread_tsd_mutex); +	  switch (key->status) +	    { +	    case _PTHREAD_TSD_KEY_INUSE:  	      arg = pthread_getspecific((pthread_key_t) k); -	      if (arg != NULL) +	      if (arg != NULL && key->destructor != NULL)  		{ +		  /* The destructor must be called with the mutex off. */ +		  pthread_mutex_unlock(&_pthread_tsd_mutex); +		  /* END CRITICAL SECTION */ + +		  /* FIXME: Is the destructor supposed to set the key value +		     to NULL? How is this done when arg is the key value, not +		     a pointer to it? For now we assume that the destructor +		     always succeeds. +		     */  		  (void) (key->destructor)(arg); + +		  /* CRITICAL SECTION */ +		  pthread_mutex_lock(&_pthread_tsd_mutex); + +		  pthread_setspecific((pthread_key_t) k, NULL); +#if 0 +		  /* Only needed if we don't assume the destructor +		     always succeeds. +		     */ +		  dirty = 1; +#endif +		} +	      break; + +	    case _PTHREAD_TSD_KEY_DELETED: +	      key->status = _PTHREAD_TSD_KEY_INUSE; +	      pthread_setspecific((pthread_key_t) k, NULL); + +	      if (key->in_use <= 0) +		{ +		  /* This is the last thread to use this +		     deleted key. It can now be made available +		     for re-use. +		   */ +		  key->status = _PTHREAD_TSD_KEY_REUSE; +		} +	      else +		{ +		  key->status = _PTHREAD_TSD_KEY_DELETED;  		} +	      break; + +	    default: +	      break;  	    } +	  pthread_mutex_unlock(&_pthread_tsd_mutex); +	  /* END CRITICAL SECTION */ +  	  key++;  	} + +      if (!dirty) +	break;      }  } @@ -26,6 +26,12 @@ DWORD _pthread_threadID_TlsIndex;  DWORD _pthread_TSD_keys_TlsIndex; +/* Function pointer to TryEnterCriticalSection if it exists; otherwise NULL */ +BOOL (WINAPI *_pthread_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL; + +/* Handle to kernel32.dll */ +static HINSTANCE _pthread_h_kernel32; +  BOOL WINAPI PthreadsEntryPoint(HINSTANCE dllHandle,  			  DWORD reason,  			  LPVOID situation) @@ -54,11 +60,16 @@ BOOL WINAPI PthreadsEntryPoint(HINSTANCE dllHandle,  	{  	  return FALSE;  	} + +      /* Load KERNEL32 and try to get address of TryEnterCriticalSection */ +      _pthread_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL")); +      _pthread_try_enter_critical_section = GetProcAddress(_pthread_h_kernel32, "TryEnterCriticalSection");        break;      case DLL_PROCESS_DETACH:        (void) TlsFree(_pthread_TSD_keys_TlsIndex);        (void) TlsFree(_pthread_threadID_TlsIndex); +      (void) FreeLibrary(_pthread_h_kernel32);        break;      default: @@ -69,3 +69,15 @@ pthread_mutex_t _pthread_tsd_mutex = PTHREAD_MUTEX_INITIALIZER;  /* Index to the next available TSD key. */  int _pthread_tsd_key_next = 0; + +/* An array of pthread_key_t */ +pthread_key_t _pthread_key_virgins[_PTHREAD_MAX_KEYS]; + +/* Index to the next available previously unused pthread_key_t */ +int _pthread_key_virgin_next; + +/* An array of pthread_key_t */ +pthread_key_t _pthread_key_reuse[_PTHREAD_MAX_KEYS]; + +/* Index to the first available reusable pthread_key_t. */ +int _pthread_key_reuse_top; diff --git a/implement.h b/implement.h index 135fc18..db6b5a2 100644 --- a/implement.h +++ b/implement.h @@ -22,7 +22,8 @@ enum {  enum {    _PTHREAD_TSD_KEY_DELETED, -  _PTHREAD_TSD_KEY_INUSE +  _PTHREAD_TSD_KEY_INUSE, +  _PTHREAD_TSD_KEY_REUSE  };  #define _PTHREAD_VALID(T) \ @@ -51,6 +52,7 @@ typedef struct _pthread_tsd_key _pthread_tsd_key_t;  struct _pthread_tsd_key {    int in_use; +  int status;    void (* destructor)(void *);  }; @@ -177,7 +179,19 @@ extern _pthread_tsd_key_t _pthread_tsd_key_table[];  /* Mutex lock for TSD operations */  extern pthread_mutex_t _pthread_tsd_mutex; -/* Index to the next available TSD key. */ -extern int _pthread_tsd_key_next; +/* Function pointer to TryEnterCriticalSection if it exists; otherwise NULL */ +extern BOOL (WINAPI *_pthread_try_enter_critical_section)(LPCRITICAL_SECTION); + +/* An array of pthread_key_t */ +extern pthread_key_t _pthread_key_virgins[]; + +/* Index to the next available previously unused pthread_key_t */ +extern int _pthread_key_virgin_next; + +/* An array of pthread_key_t */ +extern pthread_key_t _pthread_key_reuse[]; + +/* Index to the first available reusable pthread_key_t. */ +extern int _pthread_key_reuse_top;  #endif /* _IMPLEMENT_H */ @@ -88,12 +88,9 @@ pthread_mutex_unlock(pthread_mutex_t *mutex)  int  pthread_mutex_trylock(pthread_mutex_t *mutex)  { -  /* Typically evaluates to 31. */ -  int numbits = (sizeof(DWORD) * 8) - 1; - -  if ((GetVersion() >> numbits) != 1) +  if (_pthread_try_enter_critical_section == NULL)      { -      /* We're not on Windows NT; return ENOSYS. */ +      /* TryEnterCriticalSection does not exist in the OS; return ENOSYS. */        return ENOSYS;      } @@ -107,5 +104,5 @@ pthread_mutex_trylock(pthread_mutex_t *mutex)        pthread_mutex_init(mutex, NULL);      } -  return (TryEnterCriticalSection(&mutex->cs) != TRUE) ? EBUSY : 0; +  return ((*_pthread_try_enter_critical_section)(&mutex->cs) != TRUE) ? EBUSY : 0;  } @@ -120,6 +120,10 @@ _pthread_delete_thread(_pthread_t * thread)    /* We don't check that the thread has been properly cleaned up, so       it had better be done already. */ +  /* Release any keys */ + +  _pthread_destructor_run_all(); +    /* Remove the thread entry if necessary. */    if (thread != NULL @@ -65,9 +65,14 @@ pthread_key_create(pthread_key_t *key, void (*destructor)(void *))    if (_pthread_tsd_key_next >= PTHREAD_KEYS_MAX)      ret = EAGAIN; +  /* FIXME: This needs to be implemented as a list plus a re-use stack as for +     thread IDs. _pthread_destructor_run_all() then needs to be changed +     to push keys onto the re-use stack. +   */    k = _pthread_tsd_key_next++; -  _pthread_tsd_key_table[k].in_use = _PTHREAD_TSD_KEY_INUSE; +  _pthread_tsd_key_table[k].in_use = 0; +  _pthread_tsd_key_table[k].status = _PTHREAD_TSD_KEY_INUSE;    _pthread_tsd_key_table[k].destructor = destructor;    pthread_mutex_unlock(&_pthread_tsd_mutex); @@ -87,7 +92,7 @@ pthread_setspecific(pthread_key_t key, void *value)    /* CRITICAL SECTION */    pthread_mutex_lock(&_pthread_tsd_mutex); -  inuse = (_pthread_tsd_key_table[key].in_use == _PTHREAD_TSD_KEY_INUSE); +  inuse = (_pthread_tsd_key_table[key].status == _PTHREAD_TSD_KEY_INUSE);    pthread_mutex_unlock(&_pthread_tsd_mutex);    /* END CRITICAL SECTION */ @@ -96,6 +101,24 @@ pthread_setspecific(pthread_key_t key, void *value)      return EINVAL;    keys = (void **) TlsGetValue(_pthread_TSD_keys_TlsIndex); + +  if (keys[key] != NULL) +    { +      if (value == NULL) +	{ +	  /* Key is no longer in use by this thread. */ +	  _pthread_tsd_key_table[key].in_use--; +	} +    } +  else +    { +      if (value != NULL) +	{ +	  /* Key is now in use by this thread. */ +	  _pthread_tsd_key_table[key].in_use++; +	} +    } +    keys[key] = value;    return 0; @@ -110,7 +133,7 @@ pthread_getspecific(pthread_key_t key)    /* CRITICAL SECTION */    pthread_mutex_lock(&_pthread_tsd_mutex); -  inuse = (_pthread_tsd_key_table[key].in_use == _PTHREAD_TSD_KEY_INUSE); +  inuse = (_pthread_tsd_key_table[key].status == _PTHREAD_TSD_KEY_INUSE);    pthread_mutex_unlock(&_pthread_tsd_mutex);    /* END CRITICAL SECTION */ @@ -153,13 +176,13 @@ pthread_key_delete(pthread_key_t key)    /* CRITICAL SECTION */    pthread_mutex_lock(&_pthread_tsd_mutex); -  if (_pthread_tsd_key_table[key].in_use != _PTHREAD_TSD_KEY_INUSE) +  if (_pthread_tsd_key_table[key].status != _PTHREAD_TSD_KEY_INUSE)      {        ret = EINVAL;      }    else      { -      _pthread_tsd_key_table[key].in_use = _PTHREAD_TSD_KEY_DELETED; +      _pthread_tsd_key_table[key].status = _PTHREAD_TSD_KEY_DELETED;        _pthread_tsd_key_table[key].destructor = NULL;      }  | 
