summaryrefslogtreecommitdiffstats
path: root/unix
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 /unix
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 'unix')
-rw-r--r--unix/Makefile.in9
-rw-r--r--unix/tclUnixChan.c28
-rw-r--r--unix/tclUnixThrd.c36
3 files changed, 65 insertions, 8 deletions
diff --git a/unix/Makefile.in b/unix/Makefile.in
index df69f9c..c28fcb7 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -5,7 +5,7 @@
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
-# RCS: @(#) $Id: Makefile.in,v 1.63 2000/04/25 20:58:48 hobbs Exp $
+# RCS: @(#) $Id: Makefile.in,v 1.64 2000/05/02 22:02:36 kupries Exp $
VERSION = @TCL_VERSION@
@@ -274,6 +274,7 @@ GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
tclResolve.o tclResult.o tclScan.o tclStringObj.o tclThread.o \
tclStubInit.o tclStubLib.o tclTimer.o tclUtf.o tclUtil.o tclVar.o
+
STUB_LIB_OBJS = tclStubLib.o ${COMPAT_OBJS}
OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} ${COMPAT_OBJS} @DL_OBJS@
@@ -352,6 +353,7 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclTestObj.c \
$(GENERIC_DIR)/tclTestProcBodyObj.c \
$(GENERIC_DIR)/tclThread.c \
+ $(GENERIC_DIR)/tclThreadJoin.c \
$(GENERIC_DIR)/tclTimer.c \
$(GENERIC_DIR)/tclUtil.c \
$(GENERIC_DIR)/tclVar.c
@@ -473,7 +475,7 @@ topDirName:
gendate:
yacc -l $(GENERIC_DIR)/tclGetDate.y
sed -e 's/yy/TclDate/g' -e '/^#include <values.h>/d' \
- -e 's?SCCSID?RCS: @(#) $$Id: Makefile.in,v 1.63 2000/04/25 20:58:48 hobbs Exp $$?' \
+ -e 's?SCCSID?RCS: @(#) $$Id: Makefile.in,v 1.64 2000/05/02 22:02:36 kupries Exp $$?' \
-e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \
-e '/TclDatenewstate:/d' -e '/#pragma/d' \
-e '/#include <inttypes.h>/d' -e 's/const /CONST /g' \
@@ -908,6 +910,9 @@ tclTimer.o: $(GENERIC_DIR)/tclTimer.c
tclThread.o: $(GENERIC_DIR)/tclThread.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThread.c
+tclThreadJoin.o: $(GENERIC_DIR)/tclThreadJoin.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadJoin.c
+
tclThreadTest.o: $(GENERIC_DIR)/tclThreadTest.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadTest.c
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
index 1bf4818..d687c9c 100644
--- a/unix/tclUnixChan.c
+++ b/unix/tclUnixChan.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUnixChan.c,v 1.17 2000/04/19 09:17:03 hobbs Exp $
+ * RCS: @(#) $Id: tclUnixChan.c,v 1.18 2000/05/02 22:02:37 kupries Exp $
*/
#include "tclInt.h" /* Internal definitions for Tcl. */
@@ -76,8 +76,10 @@ typedef struct FileState {
int validMask; /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, or TCL_EXCEPTION: indicates
* which operations are valid on the file. */
+#ifdef DEPRECATED
struct FileState *nextPtr; /* Pointer to next file in list of all
* file channels. */
+#endif
} FileState;
#ifdef SUPPORTS_TTY
@@ -108,6 +110,7 @@ typedef struct TtyAttrs {
#endif /* !SUPPORTS_TTY */
+#ifdef DEPRECATED
typedef struct ThreadSpecificData {
/*
* List of all file channels currently open. This is per thread and is
@@ -118,6 +121,7 @@ typedef struct ThreadSpecificData {
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
+#endif
/*
* This structure describes per-instance state of a tcp based channel.
@@ -442,10 +446,13 @@ FileCloseProc(instanceData, interp)
Tcl_Interp *interp; /* For error reporting - unused. */
{
FileState *fsPtr = (FileState *) instanceData;
+#ifdef DEPRECATED
FileState **nextPtrPtr;
+#endif
int errorCode = 0;
+#ifdef DEPRECATED
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
+#endif
Tcl_DeleteFileHandler(fsPtr->fd);
/*
@@ -458,6 +465,7 @@ FileCloseProc(instanceData, interp)
errorCode = errno;
}
}
+#ifdef DEPRECATED
for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
if ((*nextPtrPtr) == fsPtr) {
@@ -465,6 +473,7 @@ FileCloseProc(instanceData, interp)
break;
}
}
+#endif
ckfree((char *) fsPtr);
return errorCode;
}
@@ -1269,7 +1278,9 @@ TclpOpenFileChannel(interp, fileName, modeString, permissions)
char channelName[16 + TCL_INTEGER_SPACE];
Tcl_DString ds, buffer;
Tcl_ChannelType *channelTypePtr;
+#ifdef DEPRECATED
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+#endif
mode = TclGetOpenMode(interp, modeString, &seekFlag);
if (mode == -1) {
@@ -1340,8 +1351,10 @@ TclpOpenFileChannel(interp, fileName, modeString, permissions)
fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
}
+#ifdef DEPRECATED
fsPtr->nextPtr = tsdPtr->firstFilePtr;
tsdPtr->firstFilePtr = fsPtr;
+#endif
fsPtr->validMask = channelPermissions | TCL_EXCEPTION;
fsPtr->fd = fd;
@@ -1403,7 +1416,9 @@ Tcl_MakeFileChannel(handle, mode)
FileState *fsPtr;
char channelName[16 + TCL_INTEGER_SPACE];
int fd = (int) handle;
+#ifdef DEPRECATED
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+#endif
if (mode == 0) {
return NULL;
@@ -1411,22 +1426,27 @@ Tcl_MakeFileChannel(handle, mode)
sprintf(channelName, "file%d", fd);
+
/*
* Look to see if a channel with this fd and the same mode already exists.
* If the fd is used, but the mode doesn't match, return NULL.
*/
-
+
+#ifdef DEPRECATED
for (fsPtr = tsdPtr->firstFilePtr; fsPtr != NULL; fsPtr = fsPtr->nextPtr) {
if (fsPtr->fd == fd) {
return ((mode|TCL_EXCEPTION) == fsPtr->validMask) ?
fsPtr->channel : NULL;
}
}
+#endif
fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
+
+#ifdef DEPRECATED
fsPtr->nextPtr = tsdPtr->firstFilePtr;
tsdPtr->firstFilePtr = fsPtr;
-
+#endif
fsPtr->fd = fd;
fsPtr->validMask = mode | TCL_EXCEPTION;
fsPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName,
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index 2e8e8a4..bbbb3f2 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -53,8 +53,6 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
#endif /* TCL_THREADS */
-
-
/*
*----------------------------------------------------------------------
*
@@ -133,6 +131,40 @@ Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags)
#endif /* TCL_THREADS */
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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, state)
+ Tcl_ThreadId id; /* Id of the thread to wait upon */
+ int* state; /* Reference to the storage the result
+ * of the thread we wait upon will be
+ * written into. */
+{
+#ifdef TCL_THREADS
+ int result;
+
+ result = pthread_join ((pthread_t) id, (VOID**) state);
+ return (result == 0) ? TCL_OK : TCL_ERROR;
+#else
+ return TCL_ERROR;
+#endif
+}
+
#ifdef TCL_THREADS
/*
*----------------------------------------------------------------------