summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
Diffstat (limited to 'win')
-rw-r--r--win/Makefile.in3
-rw-r--r--win/makefile.vc3
-rw-r--r--win/tclWinThrd.c57
3 files changed, 57 insertions, 6 deletions
diff --git a/win/Makefile.in b/win/Makefile.in
index d03e9a9..d209d0d 100644
--- a/win/Makefile.in
+++ b/win/Makefile.in
@@ -5,7 +5,7 @@
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
-# RCS: @(#) $Id: Makefile.in,v 1.33 2000/04/25 20:58:48 hobbs Exp $
+# RCS: @(#) $Id: Makefile.in,v 1.34 2000/05/02 22:02:37 kupries Exp $
VERSION = @TCL_VERSION@
@@ -255,6 +255,7 @@ GENERIC_OBJS = \
tclStubInit.$(OBJEXT) \
tclStubLib.$(OBJEXT) \
tclThread.$(OBJEXT) \
+ tclThreadJoin.$(OBJEXT) \
tclTimer.$(OBJEXT) \
tclUtf.$(OBJEXT) \
tclUtil.$(OBJEXT) \
diff --git a/win/makefile.vc b/win/makefile.vc
index 8fe5cda..5d7cab4 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -6,7 +6,7 @@
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
-# RCS: @(#) $Id: makefile.vc,v 1.50 2000/04/25 20:58:48 hobbs Exp $
+# RCS: @(#) $Id: makefile.vc,v 1.51 2000/05/02 22:02:37 kupries Exp $
# Does not depend on the presence of any environment variables in
# order to compile tcl; all needed information is derived from
@@ -178,6 +178,7 @@ TCLOBJS = \
$(TMPDIR)\tclStubInit.obj \
$(TMPDIR)\tclStubLib.obj \
$(TMPDIR)\tclThread.obj \
+ $(TMPDIR)\tclThreadJoin.obj \
$(TMPDIR)\tclTimer.obj \
$(TMPDIR)\tclUtf.obj \
$(TMPDIR)\tclUtil.obj \
diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c
index 8fe2596..b3e23fd 100644
--- a/win/tclWinThrd.c
+++ b/win/tclWinThrd.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclWinThrd.c,v 1.8 2000/04/20 01:30:20 hobbs Exp $
+ * RCS: @(#) $Id: tclWinThrd.c,v 1.9 2000/05/02 22:02:38 kupries Exp $
*/
#include "tclWinInt.h"
@@ -45,6 +45,15 @@ static CRITICAL_SECTION allocLock;
static Tcl_Mutex allocLockPtr = (Tcl_Mutex) &allocLock;
/*
+ * The joinLock serializes Create- and ExitThread. This is necessary to
+ * prevent a race where a new joinable thread exits before the creating
+ * thread had the time to create the necessary data structures in the
+ * emulation layer.
+ */
+
+static CRITICAL_SECTION joinLock;
+
+/*
* Condition variables are implemented with a combination of a
* per-thread Windows Event and a per-condition waiting queue.
* The idea is that each thread has its own Event that it waits
@@ -125,11 +134,20 @@ Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags)
{
unsigned long code;
+ EnterCriticalSection(&joinLock);
+
code = _beginthreadex(NULL, stackSize, proc, clientData, 0,
(unsigned *)idPtr);
+
if (code == 0) {
+ LeaveCriticalSection(&joinLock);
return TCL_ERROR;
} else {
+ if (flags & TCL_THREAD_JOINABLE) {
+ TclRememberJoinableThread (*idPtr);
+ }
+
+ LeaveCriticalSection(&joinLock);
return TCL_OK;
}
}
@@ -137,6 +155,33 @@ Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags)
/*
*----------------------------------------------------------------------
*
+ * Tcl_JoinThread --
+ *
+ * This procedure waits upon the exit of the specified thread.
+ *
+ * Results:
+ * TCL_OK if the wait was successful, TCL_ERROR else.
+ *
+ * Side effects:
+ * The result area is set to the exit code of the thread we
+ * waited upon.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_JoinThread(id, result)
+ Tcl_ThreadId id; /* Id of the thread to wait upon */
+ int* result; /* Reference to the storage the result
+ * of the thread we wait upon will be
+ * written into. */
+{
+ return TclJoinThread (id, result);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclpThreadExit --
*
* This procedure terminates the current thread.
@@ -154,6 +199,10 @@ void
TclpThreadExit(status)
int status;
{
+ EnterCriticalSection(&joinLock);
+ TclSignalExitThread (Tcl_GetCurrentThread (), status);
+ LeaveCriticalSection(&joinLock);
+
_endthreadex((DWORD)status);
}
@@ -609,7 +658,7 @@ TclpFinalizeThreadDataKey(keyPtr)
* Tcl_ConditionWait --
*
* This procedure is invoked to wait on a condition variable.
- * The mutex is automically released as part of the wait, and
+ * The mutex is atomically released as part of the wait, and
* automatically grabbed when the condition is signaled.
*
* The mutex must be held when this procedure is called.
@@ -647,7 +696,7 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
}
/*
- * Self initialize the two parts of the contition.
+ * Self initialize the two parts of the condition.
* The per-condition and per-thread parts need to be
* handled independently.
*/
@@ -672,7 +721,7 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
if (doExit) {
/*
* Create a per-thread exit handler to clean up the condEvent.
- * We must be careful do do this outside the Master Lock
+ * We must be careful to do this outside the Master Lock
* because Tcl_CreateThreadExitHandler uses its own
* ThreadSpecificData, and initializing that may drop
* back into the Master Lock.