diff options
Diffstat (limited to 'unix/tclUnixThrd.c')
| -rw-r--r-- | unix/tclUnixThrd.c | 218 | 
1 files changed, 109 insertions, 109 deletions
| diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index f8131c0..f475aed 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -5,20 +5,17 @@   *   * Copyright (c) 1991-1994 The Regents of the University of California.   * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 2008 by George Peter Staplin   *   * See the file "license.terms" for information on usage and redistribution of   * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * SCCS:  @(#) tclUnixThrd.c 1.18 98/02/19 14:24:12   */  #include "tclInt.h"  #ifdef TCL_THREADS -#include "pthread.h" - -typedef struct ThreadSpecificData { +typedef struct {      char nabuf[16];  } ThreadSpecificData; @@ -47,15 +44,7 @@ static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;  static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;  static pthread_mutex_t *allocLockPtr = &allocLock; -/* - * These are for the critical sections inside this file. - */ - -#define MASTER_LOCK	pthread_mutex_lock(&masterLock) -#define MASTER_UNLOCK	pthread_mutex_unlock(&masterLock) -  #endif /* TCL_THREADS */ -  /*   *---------------------------------------------------------------------- @@ -77,7 +66,7 @@ static pthread_mutex_t *allocLockPtr = &allocLock;  int  TclpThreadCreate(      Tcl_ThreadId *idPtr,	/* Return, the ID of the thread */ -    Tcl_ThreadCreateProc proc,	/* Main() function of the thread */ +    Tcl_ThreadCreateProc *proc,	/* Main() function of the thread */      ClientData clientData,	/* The one argument to Main() */      int stackSize,		/* Size of stack for the new thread */      int flags)			/* Flags controlling behaviour of the new @@ -109,18 +98,19 @@ TclpThreadCreate(  	 */  	size_t size; +  	result = pthread_attr_getstacksize(&attr, &size);  	if (!result && (size < TCL_THREAD_STACK_MIN)) {  	    pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);  	} -#endif +#endif /* TCL_THREAD_STACK_MIN */      } -#endif +#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ +      if (! (flags & TCL_THREAD_JOINABLE)) {  	pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);      } -      if (pthread_create(&theThread, &attr,  	    (void * (*)(void *))proc, (void *)clientData) &&  	    pthread_create(&theThread, NULL, @@ -157,13 +147,17 @@ int  Tcl_JoinThread(      Tcl_ThreadId threadId,	/* Id of the thread to wait upon. */      int *state)			/* Reference to the storage the result of the -				 * thread we wait upon will be written -				 * into. */ +				 * thread we wait upon will be written into. +				 * May be NULL. */  {  #ifdef TCL_THREADS      int result; +    unsigned long retcode, *retcodePtr = &retcode; -    result = pthread_join((pthread_t) threadId, (void**) state); +    result = pthread_join((pthread_t) threadId, (void**) retcodePtr); +    if (state) { +	*state = (int) retcode; +    }      return (result == 0) ? TCL_OK : TCL_ERROR;  #else      return TCL_ERROR; @@ -191,56 +185,7 @@ void  TclpThreadExit(      int status)  { -    pthread_exit((VOID *)status); -} -#endif /* TCL_THREADS */ - -#ifdef TCL_THREADS -/* - *---------------------------------------------------------------------- - * - * TclpThreadGetStackSize -- - * - *	This procedure returns the size of the current thread's stack. - * - * Results: - *	Stack size (in bytes?) or -1 for error or 0 for undeterminable. - * - * Side effects: - *	None. - * - *---------------------------------------------------------------------- - */ - -int -TclpThreadGetStackSize(void) -{ -#if defined(HAVE_PTHREAD_SETSTACKSIZE) && defined(TclpPthreadGetAttrs) -    pthread_attr_t threadAttr;	/* This will hold the thread attributes for -				 * the current thread. */ -    size_t stackSize; - -    if (pthread_attr_init(&threadAttr) != 0) { -	return -1; -    } -    if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) { -	pthread_attr_destroy(&threadAttr); -	return -1; -    } -    if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) { -	pthread_attr_destroy(&threadAttr); -	return -1; -    } -    pthread_attr_destroy(&threadAttr); -    return (int) stackSize; -#else -    /* -     * Cannot determine the real stack size of this thread. The caller might -     * want to try looking at the process accounting limits instead. -     */ - -    return 0; -#endif +    pthread_exit(INT2PTR(status));  }  #endif /* TCL_THREADS */ @@ -300,7 +245,7 @@ TclpInitLock(void)  /*   *----------------------------------------------------------------------   * - * TclpFinalizeLock + * TclFinalizeLock   *   *	This procedure is used to destroy all private resources used in this   *	file. @@ -408,7 +353,6 @@ TclpMasterUnlock(void)      pthread_mutex_unlock(&masterLock);  #endif  } -  /*   *---------------------------------------------------------------------- @@ -433,7 +377,8 @@ Tcl_Mutex *  Tcl_GetAllocMutex(void)  {  #ifdef TCL_THREADS -    return (Tcl_Mutex *)&allocLockPtr; +    pthread_mutex_t **allocLockPtrPtr = &allocLockPtr; +    return (Tcl_Mutex *) allocLockPtrPtr;  #else      return NULL;  #endif @@ -467,19 +412,20 @@ Tcl_MutexLock(      Tcl_Mutex *mutexPtr)	/* Really (pthread_mutex_t **) */  {      pthread_mutex_t *pmutexPtr; +      if (*mutexPtr == NULL) { -	MASTER_LOCK; +	pthread_mutex_lock(&masterLock);  	if (*mutexPtr == NULL) {  	    /*  	     * Double inside master lock check to avoid a race condition.  	     */ -	    pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t)); +	    pmutexPtr = ckalloc(sizeof(pthread_mutex_t));  	    pthread_mutex_init(pmutexPtr, NULL);  	    *mutexPtr = (Tcl_Mutex)pmutexPtr;  	    TclRememberMutex(mutexPtr);  	} -	MASTER_UNLOCK; +	pthread_mutex_unlock(&masterLock);      }      pmutexPtr = *((pthread_mutex_t **)mutexPtr);      pthread_mutex_lock(pmutexPtr); @@ -506,7 +452,8 @@ void  Tcl_MutexUnlock(      Tcl_Mutex *mutexPtr)	/* Really (pthread_mutex_t **) */  { -    pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr; +    pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr; +      pthread_mutex_unlock(pmutexPtr);  } @@ -533,10 +480,11 @@ void  TclpFinalizeMutex(      Tcl_Mutex *mutexPtr)  { -    pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr; +    pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr; +      if (pmutexPtr != NULL) {  	pthread_mutex_destroy(pmutexPtr); -	ckfree((char *) pmutexPtr); +	ckfree(pmutexPtr);  	*mutexPtr = NULL;      }  } @@ -567,14 +515,14 @@ void  Tcl_ConditionWait(      Tcl_Condition *condPtr,	/* Really (pthread_cond_t **) */      Tcl_Mutex *mutexPtr,	/* Really (pthread_mutex_t **) */ -    Tcl_Time *timePtr)		/* Timeout on waiting period */ +    const Tcl_Time *timePtr) /* Timeout on waiting period */  {      pthread_cond_t *pcondPtr;      pthread_mutex_t *pmutexPtr;      struct timespec ptime;      if (*condPtr == NULL) { -	MASTER_LOCK; +	pthread_mutex_lock(&masterLock);  	/*  	 * Double check inside mutex to avoid race, then initialize condition @@ -582,12 +530,12 @@ Tcl_ConditionWait(  	 */  	if (*condPtr == NULL) { -	    pcondPtr = (pthread_cond_t *) ckalloc(sizeof(pthread_cond_t)); +	    pcondPtr = ckalloc(sizeof(pthread_cond_t));  	    pthread_cond_init(pcondPtr, NULL); -	    *condPtr = (Tcl_Condition)pcondPtr; +	    *condPtr = (Tcl_Condition) pcondPtr;  	    TclRememberCondition(condPtr);  	} -	MASTER_UNLOCK; +	pthread_mutex_unlock(&masterLock);      }      pmutexPtr = *((pthread_mutex_t **)mutexPtr);      pcondPtr = *((pthread_cond_t **)condPtr); @@ -666,9 +614,10 @@ TclpFinalizeCondition(      Tcl_Condition *condPtr)  {      pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr; +      if (pcondPtr != NULL) {  	pthread_cond_destroy(pcondPtr); -	ckfree((char *) pcondPtr); +	ckfree(pcondPtr);  	*condPtr = NULL;      }  } @@ -677,7 +626,7 @@ TclpFinalizeCondition(  /*   *----------------------------------------------------------------------   * - * TclpReaddir, TclpLocaltime, TclpGmtime, TclpInetNtoa -- + * TclpReaddir, TclpInetNtoa --   *   *	These procedures replace core C versions to be used in a threaded   *	environment. @@ -695,6 +644,7 @@ TclpFinalizeCondition(   *----------------------------------------------------------------------   */ +#ifndef TCL_NO_DEPRECATED  Tcl_DirEntry *  TclpReaddir(      DIR * dir) @@ -702,24 +652,22 @@ TclpReaddir(      return TclOSreaddir(dir);  } +#undef TclpInetNtoa  char *  TclpInetNtoa(      struct in_addr addr)  {  #ifdef TCL_THREADS      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -    union { -	unsigned long l; -	unsigned char b[4]; -    } u; +    unsigned char *b = (unsigned char*) &addr.s_addr; -    u.l = (unsigned long) addr.s_addr; -    sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", u.b[0], u.b[1], u.b[2], u.b[3]); +    sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);      return tsdPtr->nabuf;  #else      return inet_ntoa(addr);  #endif  } +#endif /* TCL_NO_DEPRECATED */  #ifdef TCL_THREADS  /* @@ -727,10 +675,9 @@ TclpInetNtoa(   */  #ifdef USE_THREAD_ALLOC -static volatile int initialized = 0;  static pthread_key_t key; -typedef struct allocMutex { +typedef struct {      Tcl_Mutex tlock;      pthread_mutex_t plock;  } allocMutex; @@ -738,13 +685,15 @@ typedef struct allocMutex {  Tcl_Mutex *  TclpNewAllocMutex(void)  { -    struct allocMutex *lockPtr; +    allocMutex *lockPtr; +    register pthread_mutex_t *plockPtr; -    lockPtr = malloc(sizeof(struct allocMutex)); +    lockPtr = malloc(sizeof(allocMutex));      if (lockPtr == NULL) {  	Tcl_Panic("could not allocate lock");      } -    lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock; +    plockPtr = &lockPtr->plock; +    lockPtr->tlock = (Tcl_Mutex) plockPtr;      pthread_mutex_init(&lockPtr->plock, NULL);      return &lockPtr->tlock;  } @@ -762,38 +711,37 @@ TclpFreeAllocMutex(  }  void +TclpInitAllocCache(void) +{ +    pthread_key_create(&key, NULL); +} + +void  TclpFreeAllocCache(      void *ptr)  {      if (ptr != NULL) {  	/* -	 * Called by the pthread lib when a thread exits +	 * Called by TclFinalizeThreadAllocThread() during the thread +	 * finalization initiated from Tcl_FinalizeThread()  	 */  	TclFreeAllocCache(ptr); +	pthread_setspecific(key, NULL); -    } else if (initialized) { +    } else {  	/* -	 * Called by us in TclFinalizeThreadAlloc() during the library +	 * Called by TclFinalizeThreadAlloc() during the process  	 * finalization initiated from Tcl_Finalize()  	 */  	pthread_key_delete(key); -	initialized = 0;      }  }  void *  TclpGetAllocCache(void)  { -    if (!initialized) { -	pthread_mutex_lock(allocLockPtr); -	if (!initialized) { -	    pthread_key_create(&key, TclpFreeAllocCache); -	    initialized = 1; -	} -	pthread_mutex_unlock(allocLockPtr); -    }      return pthread_getspecific(key);  } @@ -804,6 +752,58 @@ TclpSetAllocCache(      pthread_setspecific(key, arg);  }  #endif /* USE_THREAD_ALLOC */ + +void * +TclpThreadCreateKey(void) +{ +    pthread_key_t *ptkeyPtr; + +    ptkeyPtr = TclpSysAlloc(sizeof *ptkeyPtr, 0); +    if (NULL == ptkeyPtr) { +	Tcl_Panic("unable to allocate thread key!"); +    } + +    if (pthread_key_create(ptkeyPtr, NULL)) { +	Tcl_Panic("unable to create pthread key!"); +    } + +    return ptkeyPtr; +} + +void +TclpThreadDeleteKey( +    void *keyPtr) +{ +    pthread_key_t *ptkeyPtr = keyPtr; + +    if (pthread_key_delete(*ptkeyPtr)) { +	Tcl_Panic("unable to delete key!"); +    } + +    TclpSysFree(keyPtr); +} + +void +TclpThreadSetMasterTSD( +    void *tsdKeyPtr, +    void *ptr) +{ +    pthread_key_t *ptkeyPtr = tsdKeyPtr; + +    if (pthread_setspecific(*ptkeyPtr, ptr)) { +	Tcl_Panic("unable to set master TSD value"); +    } +} + +void * +TclpThreadGetMasterTSD( +    void *tsdKeyPtr) +{ +    pthread_key_t *ptkeyPtr = tsdKeyPtr; + +    return pthread_getspecific(*ptkeyPtr); +} +  #endif /* TCL_THREADS */  /* | 
