summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixThrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r--unix/tclUnixThrd.c178
1 files changed, 71 insertions, 107 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index bc80e00..0469d7a 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -5,6 +5,7 @@
*
* 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.
@@ -14,7 +15,7 @@
#ifdef TCL_THREADS
-#include "pthread.h"
+#include <pthread.h>
typedef struct ThreadSpecificData {
char nabuf[16];
@@ -53,7 +54,6 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
#define MASTER_UNLOCK pthread_mutex_unlock(&masterLock)
#endif /* TCL_THREADS */
-
/*
*----------------------------------------------------------------------
@@ -75,7 +75,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
@@ -107,18 +107,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,
@@ -197,99 +198,6 @@ TclpThreadExit(
}
#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.
- *
- *----------------------------------------------------------------------
- */
-
-size_t
-TclpThreadGetStackSize(void)
-{
- size_t stackSize = 0;
-#if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && defined(TclpPthreadGetAttrs)
- pthread_attr_t threadAttr; /* This will hold the thread attributes for
- * the current thread. */
-#ifdef __GLIBC__
- /*
- * Fix for [Bug 1815573]
- *
- * DESCRIPTION:
- * On linux TclpPthreadGetAttrs (which is pthread_attr_get_np) may return
- * bogus values on the initial thread.
- *
- * ASSUMPTIONS:
- * There seems to be no api to determine if we are on the initial
- * thread. The simple scheme implemented here assumes:
- * 1. The first Tcl interp to be created lives in the initial thread. If
- * this assumption is not true, the fix is to call
- * TclpThreadGetStackSize from the initial thread previous to
- * creating any Tcl interpreter. In this case, especially if another
- * Tcl interpreter may be created in the initial thread, it might be
- * better to enable the second branch in the #if below
- * 2. There will be no races in creating the first Tcl interp - ie, the
- * second Tcl interp will be created only after the first call to
- * Tcl_CreateInterp returns.
- *
- * These assumptions are satisfied by tclsh. Embedders on linux may want
- * to check their validity, and possibly adapt the code on failing to meet
- * them.
- */
-
- static int initialized = 0;
-
- if (!initialized) {
- initialized = 1;
- return 0;
- } else {
-#else
- {
-#endif
- if (pthread_attr_init(&threadAttr) != 0) {
- return -1;
- }
- if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) {
- pthread_attr_destroy(&threadAttr);
- return (size_t)-1;
- }
- }
-
-
- if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) {
- pthread_attr_destroy(&threadAttr);
- return (size_t)-1;
- }
- pthread_attr_destroy(&threadAttr);
-#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP)
-#ifdef __APPLE__
- /*
- * On Darwin, the API below does not return the correct stack size for the
- * main thread (which is not a real pthread), so fallback to getrlimit().
- */
- if (!pthread_main_np())
-#endif
- stackSize = pthread_get_stacksize_np(pthread_self());
-#else
- /*
- * Cannot determine the real stack size of this thread. The caller might
- * want to try looking at the process accounting limits instead.
- */
-#endif
- return stackSize;
-}
-#endif /* TCL_THREADS */
-
/*
*----------------------------------------------------------------------
*
@@ -514,6 +422,7 @@ Tcl_MutexLock(
Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
{
pthread_mutex_t *pmutexPtr;
+
if (*mutexPtr == NULL) {
MASTER_LOCK;
if (*mutexPtr == NULL) {
@@ -521,7 +430,7 @@ Tcl_MutexLock(
* 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);
@@ -553,7 +462,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);
}
@@ -580,10 +490,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;
}
}
@@ -614,7 +525,7 @@ 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;
@@ -629,9 +540,9 @@ 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;
@@ -713,9 +624,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;
}
}
@@ -849,6 +761,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 */
/*