Subject: Initial work on SF FRQ #3567063.

From: Joe Mistachkin <[email-masked]>
Date: Thu, 13 Sep 2012 18:30:41 +0000

---
 win/tclWinThrd.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c
index 13fd411..7abcc29 100644
--- a/win/tclWinThrd.c
+++ b/win/tclWinThrd.c
@@ -13,6 +13,7 @@
 #include "tclWinInt.h"
 
 #include <fcntl.h>
+#include <float.h>
 #include <io.h>
 #include <sys/stat.h>
 
@@ -122,6 +123,52 @@ typedef struct WinCondition {
     struct ThreadSpecificData *lastPtr;
 } WinCondition;
 
+/*
+ * 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 = _MCW_EM | _MCW_RC | _MCW_PC | _MCW_DN;
+
+    if (!winThreadPtr) {
+	return TCL_ERROR;
+    }
+
+    _controlfp(winThreadPtr->fpControl, fpmask);
+    return winThreadPtr->lpStartAddress(winThreadPtr->lpParameter);
+}
 
 /*
  *----------------------------------------------------------------------
@@ -149,17 +196,22 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
     int flags;				/* Flags controlling behaviour of
 					 * the new thread */
 {
+    WinThread *winThreadPtr;		/* Per-thread startup info */
     HANDLE tHandle;
 
+    winThreadPtr = (WinThread *)ckalloc(sizeof(WinThread));
+    winThreadPtr->lpStartAddress = proc;
+    winThreadPtr->lpParameter = clientData;
+    winThreadPtr->fpControl = _controlfp(0, 0);
+
     EnterCriticalSection(&joinLock);
 
 #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,
+	    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) {
-- 
cgit v0.12