summaryrefslogtreecommitdiffstats
path: root/win/tclWinThrd.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2012-11-14 09:58:36 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2012-11-14 09:58:36 (GMT)
commit37e6c3852b68f12e24e223e1a1a5d30b1bafb13f (patch)
tree2e5ee3ee0c9f4fd5f436f38d2700abd04cc92ba3 /win/tclWinThrd.c
parent31d3de9d3e64ea54a0af4ab3ff9a23c6b42b033a (diff)
parent47871a70f2f72a07a20bcf8ab3826068bf227392 (diff)
downloadtcl-37e6c3852b68f12e24e223e1a1a5d30b1bafb13f.zip
tcl-37e6c3852b68f12e24e223e1a1a5d30b1bafb13f.tar.gz
tcl-37e6c3852b68f12e24e223e1a1a5d30b1bafb13f.tar.bz2
merge trunkfrq_3579001
Diffstat (limited to 'win/tclWinThrd.c')
-rw-r--r--win/tclWinThrd.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c
index 102fd40..7b0f6f8 100644
--- a/win/tclWinThrd.c
+++ b/win/tclWinThrd.c
@@ -13,8 +13,17 @@
#include "tclWinInt.h"
+#include <float.h>
#include <sys/stat.h>
+/* Workaround for mingw versions which don't provide this in float.h */
+#ifndef _MCW_EM
+# define _MCW_EM 0x0008001F /* Error masks */
+# define _MCW_RC 0x00000300 /* Rounding */
+# define _MCW_PC 0x00030000 /* Precision */
+_CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask);
+#endif
+
/*
* This is the master lock used to serialize access to other serialization
* data structures.
@@ -124,6 +133,66 @@ typedef struct allocMutex {
#endif /* USE_THREAD_ALLOC */
/*
+ * The per thread data passed from TclpThreadCreate
+ * to TclWinThreadStart.
+ */
+
+typedef struct WinThread {
+ LPTHREAD_START_ROUTINE lpStartAddress; /* Original startup routine */
+ LPVOID lpParameter; /* Original startup data */
+ unsigned int fpControl; /* Floating point control word from the
+ * main thread */
+} WinThread;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclWinThreadStart --
+ *
+ * This procedure is the entry point for all new threads created
+ * by Tcl on Windows.
+ *
+ * Results:
+ * Various, depending on the result of the wrapped thread start
+ * routine.
+ *
+ * Side effects:
+ * Arbitrary, since user code is executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static DWORD WINAPI
+TclWinThreadStart(
+ LPVOID lpParameter) /* The WinThread structure pointer passed
+ * from TclpThreadCreate */
+{
+ WinThread *winThreadPtr = (WinThread *) lpParameter;
+ unsigned int fpmask;
+ LPTHREAD_START_ROUTINE lpOrigStartAddress;
+ LPVOID lpOrigParameter;
+
+ if (!winThreadPtr) {
+ return TCL_ERROR;
+ }
+
+ fpmask = _MCW_EM | _MCW_RC | _MCW_PC;
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200
+ fpmask |= _MCW_DN;
+#endif
+
+ _controlfp(winThreadPtr->fpControl, fpmask);
+
+ lpOrigStartAddress = winThreadPtr->lpStartAddress;
+ lpOrigParameter = winThreadPtr->lpParameter;
+
+ ckfree((char *)winThreadPtr);
+ return lpOrigStartAddress(lpOrigParameter);
+}
+
+/*
*----------------------------------------------------------------------
*
* TclpThreadCreate --
@@ -149,8 +218,14 @@ TclpThreadCreate(
int flags) /* Flags controlling behaviour of the new
* thread. */
{
+ WinThread *winThreadPtr; /* Per-thread startup info */
HANDLE tHandle;
+ winThreadPtr = (WinThread *)ckalloc(sizeof(WinThread));
+ winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc;
+ winThreadPtr->lpParameter = clientData;
+ winThreadPtr->fpControl = _controlfp(0, 0);
+
EnterCriticalSection(&joinLock);
*idPtr = 0; /* must initialize as Tcl_Thread is a pointer and
@@ -158,12 +233,12 @@ TclpThreadCreate(
*/
#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
- tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, proc,
- clientData, 0, (unsigned *)idPtr);
+ tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize,
+ (Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr,
+ 0, (unsigned *)idPtr);
#else
tHandle = CreateThread(NULL, (DWORD) stackSize,
- (LPTHREAD_START_ROUTINE) proc, (LPVOID) clientData,
- (DWORD) 0, (LPDWORD)idPtr);
+ TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr);
#endif
if (tHandle == NULL) {