diff options
author | kupries <kupries> | 2000-05-02 22:02:32 (GMT) |
---|---|---|
committer | kupries <kupries> | 2000-05-02 22:02:32 (GMT) |
commit | bfac38b888b4dee3f80767f8da8691a1154891b7 (patch) | |
tree | 73773fe6b41f1aec6a847be17c221d4a5ee4cd27 /win | |
parent | 492f9b8edd489f07ffd0741d0e9f23c0433334f9 (diff) | |
download | tcl-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.in | 3 | ||||
-rw-r--r-- | win/makefile.vc | 3 | ||||
-rw-r--r-- | win/tclWinThrd.c | 57 |
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. |