diff options
| author | dgp <dgp@users.sourceforge.net> | 2012-11-13 21:22:21 (GMT) | 
|---|---|---|
| committer | dgp <dgp@users.sourceforge.net> | 2012-11-13 21:22:21 (GMT) | 
| commit | 3f287b172483efb85cfdf6b3685fe44c9897abcf (patch) | |
| tree | 1db5e1e5f652bd123c197c109efa6c03108204fe | |
| parent | a4d552f93c2ab129b82405cb45b7e2324a67cbd7 (diff) | |
| parent | c45b50173ca951f918919aedca75f22bf1ccf7b3 (diff) | |
| download | tcl-3f287b172483efb85cfdf6b3685fe44c9897abcf.zip tcl-3f287b172483efb85cfdf6b3685fe44c9897abcf.tar.gz tcl-3f287b172483efb85cfdf6b3685fe44c9897abcf.tar.bz2  | |
360894 Threads inherit floating point config from their creator thread.
| -rw-r--r-- | win/tclWinThrd.c | 75 | 
1 files changed, 71 insertions, 4 deletions
diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index 8544e71..96c8894 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -12,6 +12,7 @@  #include "tclWinInt.h" +#include <float.h>  #include <sys/stat.h>  /* @@ -123,6 +124,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 -- @@ -148,8 +209,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 @@ -157,12 +224,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) {  | 
