diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2012-11-14 09:58:36 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2012-11-14 09:58:36 (GMT) |
commit | 37e6c3852b68f12e24e223e1a1a5d30b1bafb13f (patch) | |
tree | 2e5ee3ee0c9f4fd5f436f38d2700abd04cc92ba3 /win/tclWinThrd.c | |
parent | 31d3de9d3e64ea54a0af4ab3ff9a23c6b42b033a (diff) | |
parent | 47871a70f2f72a07a20bcf8ab3826068bf227392 (diff) | |
download | tcl-37e6c3852b68f12e24e223e1a1a5d30b1bafb13f.zip tcl-37e6c3852b68f12e24e223e1a1a5d30b1bafb13f.tar.gz tcl-37e6c3852b68f12e24e223e1a1a5d30b1bafb13f.tar.bz2 |
merge trunkfrq_3579001
Diffstat (limited to 'win/tclWinThrd.c')
-rw-r--r-- | win/tclWinThrd.c | 83 |
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) { |