summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixThrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r--unix/tclUnixThrd.c176
1 files changed, 106 insertions, 70 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index 789dbb6..ad36242 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -5,7 +5,6 @@
*
* 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.
@@ -52,6 +51,7 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
#define MASTER_UNLOCK pthread_mutex_unlock(&masterLock)
#endif /* TCL_THREADS */
+
/*
*----------------------------------------------------------------------
@@ -73,7 +73,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
@@ -105,19 +105,18 @@ 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 /* TCL_THREAD_STACK_MIN */
+#endif
}
-#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
-
+#endif
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,
@@ -196,6 +195,99 @@ 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 */
+
/*
*----------------------------------------------------------------------
*
@@ -420,7 +512,6 @@ Tcl_MutexLock(
Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
{
pthread_mutex_t *pmutexPtr;
-
if (*mutexPtr == NULL) {
MASTER_LOCK;
if (*mutexPtr == NULL) {
@@ -428,7 +519,7 @@ Tcl_MutexLock(
* Double inside master lock check to avoid a race condition.
*/
- pmutexPtr = ckalloc(sizeof(pthread_mutex_t));
+ pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t));
pthread_mutex_init(pmutexPtr, NULL);
*mutexPtr = (Tcl_Mutex)pmutexPtr;
TclRememberMutex(mutexPtr);
@@ -460,8 +551,7 @@ 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);
}
@@ -488,11 +578,10 @@ 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(pmutexPtr);
+ ckfree((char *) pmutexPtr);
*mutexPtr = NULL;
}
}
@@ -523,7 +612,7 @@ void
Tcl_ConditionWait(
Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
- const Tcl_Time *timePtr) /* Timeout on waiting period */
+ Tcl_Time *timePtr) /* Timeout on waiting period */
{
pthread_cond_t *pcondPtr;
pthread_mutex_t *pmutexPtr;
@@ -538,9 +627,9 @@ Tcl_ConditionWait(
*/
if (*condPtr == NULL) {
- pcondPtr = ckalloc(sizeof(pthread_cond_t));
+ pcondPtr = (pthread_cond_t *) ckalloc(sizeof(pthread_cond_t));
pthread_cond_init(pcondPtr, NULL);
- *condPtr = (Tcl_Condition) pcondPtr;
+ *condPtr = (Tcl_Condition)pcondPtr;
TclRememberCondition(condPtr);
}
MASTER_UNLOCK;
@@ -622,10 +711,9 @@ TclpFinalizeCondition(
Tcl_Condition *condPtr)
{
pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
-
if (pcondPtr != NULL) {
pthread_cond_destroy(pcondPtr);
- ckfree(pcondPtr);
+ ckfree((char *) pcondPtr);
*condPtr = NULL;
}
}
@@ -759,58 +847,6 @@ 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 */
/*