summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorkupries <kupries>2000-05-02 22:02:32 (GMT)
committerkupries <kupries>2000-05-02 22:02:32 (GMT)
commitbfac38b888b4dee3f80767f8da8691a1154891b7 (patch)
tree73773fe6b41f1aec6a847be17c221d4a5ee4cd27 /win
parent492f9b8edd489f07ffd0741d0e9f23c0433334f9 (diff)
downloadtcl-bfac38b888b4dee3f80767f8da8691a1154891b7.zip
tcl-bfac38b888b4dee3f80767f8da8691a1154891b7.tar.gz
tcl-bfac38b888b4dee3f80767f8da8691a1154891b7.tar.bz2
2000-05-02 Andreas Kupries <a.kupries@westend.com>
* Overall changes: (1) Implementation of joinable threads for all platforms. (2) Additional API's for channels. Required to allow the thread extension to move channels between threads. * generic/tcl.decls (lines 1360f): Added Tcl_JoinThread, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting and Tcl_ClearChannelHandlers (slots 394 to 400). * generic/tclIO.c: Implemented Tcl_IsChannelRegistered, Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting and Tcl_ClearChannelHandlers. Tcl_CutChannel uses code from CloseChannel. Replaced this code by a call to Tcl_CutChannel. Replaced several code fragments adding channels to the channel list with calls to Tcl_SpliceChannel. Removed now unused variables from CloseChannel and Tcl_UnstackChannel. Tcl_ClearChannelHandlers uses code from Tcl_Close. Replaced this code by a call to Tcl_ClearChannelHandlers. Removed now unused variables from Tcl_Close. Added the subcommands 'cut', 'forgetch', 'splice' and 'isshared' to the test code (TclTestChannelCmd). * unix/tclUnixThread.c: Implemented Tcl_JoinThread using the pthread-functionality. * win/tclWinThrd.c: Fixed several small typos in comments. Implemented Tcl_JoinThread using a platform independent emulation layer (see generic/tclThreadJoin.c below). Added 'joinLock' to serialize Tcl_CreateThread and TclpExitThread to prevent a race for joinable threads. * mac/tclMacThrd.c: Implemented Tcl_JoinThread using a platform independent emulation layer (see generic/tclThreadJoin.c below). Due to the cooperative nature of threading on this platform the race mentioned above is not present. * generic/tclThreadJoin.c: New file. Contains a platform independent emulation layer helping in the implementation of joinable threads for the win and mac platforms. * generic/tclInt.h: Added declarations for TclJoinThread, TclRememberJoinableThread and TclSignalExitThread. These procedures define the API of the emulation layer for joinable threads (see generic/tclThreadJoin.c above). * win/Makefile.in: * win/makefile.vc: Added generic/tclTheadJoin.o to the rules. * mac/: I don't know to which file generic/tclTheadJoin.o has to be added to so that it compiles. Sorry. * unix/tclUnixChan.c: #ifdef'd the thread-local list of file channels as it prevents us from transfering channels. To restore this we may need an extended interface to drivers in the future. Target: 9.0. Found while testing the new transfer of channels. The information in this list for a channel was left behind and then crashed the system during finalization. * generic/tclThreadTest.c: Added -joinable flag to 'testthread create'. Added subcommand 'testthread join'. * doc/CrtChannel.3: Added documentation for Tcl_IsChannelRegistered, Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting and Tcl_ClearChannelHandlers. * doc/Thread.3: Added documentation for Tcl_JoinThread. * tests/thread.test: Added tests for joining of threads.
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.