diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c index e69de29bb..e30021a56 100644 --- a/src/libCom/osi/os/WIN32/osdThread.c +++ b/src/libCom/osi/os/WIN32/osdThread.c @@ -0,0 +1,387 @@ + +/* + * $Id$ + * + * Author: Jeff Hill + * + * + * + */ + +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "shareLib.h" +#include "osiThread.h" +#include "cantProceed.h" +#include "errlog.h" +#include "epicsAssert.h" + +typedef struct { + HANDLE handle; + THREADFUNC funptr; + void *parm; + char *pName; + int priority; + DWORD id; +} win32ThreadParam; + +static DWORD tlsIndexWIN32 = 0xFFFFFFFF; + +/* + * threadGetOsiPriorityValue () + */ +epicsShareFunc int epicsShareAPI threadGetOsiPriorityValue (int osdPriority) +{ + int osiPriority; + + if (osdPriorityTHREAD_PRIORITY_TIME_CRITICAL) { + return threadPriorityMax; + } + + osiPriority = osdPriority - THREAD_BASE_PRIORITY_IDLE; + osiPriority *= threadPriorityMax - threadPriorityMin; + osiPriority /= THREAD_PRIORITY_TIME_CRITICAL - THREAD_BASE_PRIORITY_IDLE; + osiPriority += threadPriorityMin; + return osiPriority; +} + +/* + * threadGetOssPriorityValue () + */ +epicsShareFunc int epicsShareAPI threadGetOssPriorityValue (unsigned osiPriority) +{ + unsigned osdPriority; + + if (osiPrioritythreadPriorityMax) { + return THREAD_PRIORITY_TIME_CRITICAL; + } + + osdPriority = osiPriority - threadPriorityMin; + osdPriority *= THREAD_PRIORITY_TIME_CRITICAL - THREAD_BASE_PRIORITY_IDLE; + osdPriority /= threadPriorityMax - threadPriorityMin; + osdPriority += THREAD_BASE_PRIORITY_IDLE; + return osdPriority; +} + +/* + * threadGetStackSize () + */ +epicsShareFunc unsigned int epicsShareAPI threadGetStackSize (threadStackSizeClass stackSizeClass) +{ + static const unsigned stackSizeTable[threadStackBig+1] = {4000, 6000, 11000}; + + if (stackSizeClassthreadStackBig) { + errlogPrintf("threadGetStackSize illegal argument (too large)"); + return stackSizeTable[threadStackBig]; + } + + return stackSizeTable[stackSizeClass]; +} + +/* + * epicsWin32ThreadEntry() + */ +static DWORD WINAPI epicsWin32ThreadEntry (LPVOID lpParameter) +{ + win32ThreadParam *pParm = (win32ThreadParam *) lpParameter; + BOOL stat; + + stat = TlsSetValue (tlsIndexWIN32, pParm); + if (stat) { + return 0; + } + + (*pParm->funptr) (pParm->parm); + + CloseHandle (pParm->handle); + free (pParm->pName); + free (pParm); + + return 1; +} + +/* + * freeThreadLocalStorageIndex () + */ +static void freeThreadLocalStorageIndex (void) +{ + if (tlsIndexWIN32!=0xFFFFFFFF) { + TlsFree (tlsIndexWIN32); + } +} + +/* + * threadCreate() + */ +epicsShareFunc threadId epicsShareAPI threadCreate (const char *pName, + unsigned int priority, unsigned int stackSize, THREADFUNC pFunc,void *pParm) +{ + win32ThreadParam *pParmWIN32; + DWORD wstat; + BOOL bstat; + + if (tlsIndexWIN32==0xFFFFFFFF) { + tlsIndexWIN32 = TlsAlloc(); + if (tlsIndexWIN32==0xFFFFFFFF) { + return NULL; + } + else { + int status; + status = atexit (freeThreadLocalStorageIndex); + if (status) { + TlsFree (tlsIndexWIN32); + tlsIndexWIN32 = 0xFFFFFFFF; + return NULL; + } + } + } + + pParmWIN32 = malloc (sizeof(*pParmWIN32)); + if (pParmWIN32==NULL) { + return NULL; + } + + pParmWIN32->pName = malloc (strlen(pName)+1); + if (pParmWIN32->pName==NULL) { + free (pParmWIN32); + return NULL; + } + strcpy (pParmWIN32->pName, pName); + + pParmWIN32->funptr = pFunc; + pParmWIN32->parm = pParm; + pParmWIN32->priority = threadGetOssPriorityValue (priority); + pParmWIN32->handle = CreateThread (NULL, stackSize, epicsWin32ThreadEntry, + pParmWIN32, CREATE_SUSPENDED , &pParmWIN32->id); + if (pParmWIN32->handle==NULL) { + free (pParmWIN32->pName); + free (pParmWIN32); + return NULL; + } + + bstat = SetThreadPriority (pParmWIN32->handle, pParmWIN32->priority); + if (!bstat) { + CloseHandle (pParmWIN32->handle); + free (pParmWIN32->pName); + free (pParmWIN32); + return NULL; + } + + wstat = ResumeThread (pParmWIN32->handle); + if (wstat==0xFFFFFFFF) { + CloseHandle (pParmWIN32->handle); + free (pParmWIN32->pName); + free (pParmWIN32); + return NULL; + } + + return (threadId) pParmWIN32; +} + +/* + * threadDestroy () + */ +epicsShareFunc void epicsShareAPI threadDestroy (threadId id) +{ + win32ThreadParam *pParm = (win32ThreadParam *) id; + BOOL stat; + + stat = TerminateThread (pParm->handle, 0); + assert (stat); + + CloseHandle (pParm->handle); + free (pParm->pName); + free (pParm); + + printf ("threadDestroy() appears to be reckless on windows\n"); +} + +/* + * threadSuspend () + */ +epicsShareFunc void epicsShareAPI threadSuspend (threadId id) +{ + win32ThreadParam *pParm = (win32ThreadParam *) id; + DWORD stat; + + stat = SuspendThread (pParm->handle); + assert (stat!=0xFFFFFFFF); +} + +/* + * threadResume () + */ +epicsShareFunc void epicsShareAPI threadResume (threadId id) +{ + win32ThreadParam *pParm = (win32ThreadParam *) id; + DWORD stat; + + stat = ResumeThread (pParm->handle); + assert (stat!=0xFFFFFFFF); +} + +/* + * threadGetPriority () + */ +epicsShareFunc unsigned epicsShareAPI threadGetPriority (threadId id) +{ + win32ThreadParam *pParm = (win32ThreadParam *) id; + int win32ThreadPriority; + + win32ThreadPriority = GetThreadPriority (pParm->handle); + assert (win32ThreadPriority!=THREAD_PRIORITY_ERROR_RETURN); + + return threadGetOsiPriorityValue (win32ThreadPriority); +} + +/* + * threadSetPriority () + */ +epicsShareFunc void epicsShareAPI threadSetPriority (threadId id, unsigned priority) +{ + win32ThreadParam *pParm = (win32ThreadParam *) id; + BOOL stat; + + stat = SetThreadPriority (pParm->handle, threadGetOssPriorityValue(priority)); + assert (stat); +} + +/* + * threadSetDestroySafe () + */ +epicsShareFunc void epicsShareAPI threadSetDestroySafe () +{ + /* + * no matching windows functionality ? + */ + printf ("unable to create functionally correct threadSetDestroySafe() on win32\n"); +} + +/* + * threadSetDestroyUnsafe () + */ +epicsShareFunc void epicsShareAPI threadSetDestroyUnsafe () +{ + /* + * no matching windows functionality ? + */ + printf ("unable to create functionally correct threadSetDestroyUnsafe() on win32\n"); +} + +/* + * threadGetName () + */ +epicsShareFunc const char * epicsShareAPI threadGetName (threadId id) +{ + win32ThreadParam *pParm = (win32ThreadParam *) id; + + return pParm->pName; +} + +/* + * threadIsEqual () + */ +epicsShareFunc int epicsShareAPI threadIsEqual (threadId id1, threadId id2) +{ + win32ThreadParam *pParm1 = (win32ThreadParam *) id1; + win32ThreadParam *pParm2 = (win32ThreadParam *) id2; + + return ( pParm1->id == pParm2->id ); +} + +/* + * threadIsReady () + */ +epicsShareFunc int epicsShareAPI threadIsReady (threadId id) +{ + printf ("unable to create functionally correct threadIsReady() on win32\n"); + return 1; +} + +/* + * threadIsSuspended () + */ +epicsShareFunc int epicsShareAPI threadIsSuspended (threadId id) +{ + printf ("unable to create functionally correct threadIsSuspended() on win32\n"); + return 0; +} + +/* + * threadSleep () + */ +epicsShareFunc void epicsShareAPI threadSleep (double seconds) +{ + static const double mSecPerSec = 1000; + DWORD milliSecDelay = (DWORD) (seconds * mSecPerSec); + + Sleep (milliSecDelay); +} + +/* + * threadGetIdSelf () + */ +epicsShareFunc threadId epicsShareAPI threadGetIdSelf (void) +{ + return (threadId) TlsGetValue (tlsIndexWIN32); +} + +/* + * threadLockContextSwitch () + */ +epicsShareFunc void epicsShareAPI threadLockContextSwitch (void) +{ + win32ThreadParam *pParm; + BOOL stat; + + pParm = (win32ThreadParam *) TlsGetValue (tlsIndexWIN32); + assert (pParm); + + stat = SetThreadPriority (pParm->handle, THREAD_PRIORITY_TIME_CRITICAL); + assert (stat); + + printf ("I doubt that this is a correct implementation of threadLockContextSwitch()\n"); +} + +/* + * threadUnlockContextSwitch () + */ +epicsShareFunc void epicsShareAPI threadUnlockContextSwitch (void) +{ + win32ThreadParam *pParm; + BOOL stat; + + pParm = (win32ThreadParam *) TlsGetValue (tlsIndexWIN32); + assert (pParm); + + stat = SetThreadPriority (pParm->handle, pParm->priority); + assert (stat); + + printf ("I doubt that this is a correct implementation of threadUnlockContextSwitch()\n"); +} + +/* + * threadNameToId () + */ +epicsShareFunc threadId epicsShareAPI threadNameToId (const char *name) +{ + printf ("threadNameToId() isnt implemented\n"); + return 0; +} diff --git a/src/libCom/osi/os/WIN32/osdThread.h b/src/libCom/osi/os/WIN32/osdThread.h index 3a66d797f..fbfb1d002 100644 --- a/src/libCom/osi/os/WIN32/osdThread.h +++ b/src/libCom/osi/os/WIN32/osdThread.h @@ -2,7 +2,7 @@ #ifndef osdThreadh #define osdThreadh -#include +#include #ifndef VC_EXTRALEAN # define VC_EXTRALEAN @@ -13,32 +13,31 @@ /* including less than this causes conflicts with winsock2.h :-( */ #include -struct osdThreadPrivate +typedef struct osdThreadPrivate { -#ifdef __cpluplus - osdThreadPrivate (); - ~osdThreadPrivate (); -#endif DWORD key; -}; +} osdThreadPrivate; -#ifdef __cpluplus - -template -inline T *osiThreadPrivate::get () +epicsShareFunc INLINE threadVarId epicsShareAPI threadPrivateCreate () { - return static_cast (TlsGetValue (this->key)); + osdThreadPrivate *p = (osdThreadPrivate *) malloc (sizeof (*p)); + if (p) { + p->key = TlsAlloc (); + if (p->key==0xFFFFFFFF) { + free (p); + p = 0; + } + } + return (threadVarId) p; } -template -inline void osiThreadPrivate::set (T *pIn) +epicsShareFunc INLINE void epicsShareAPI threadPrivateDelete (threadVarId id) { - BOOL stat = TlsSetValue (this->key, static_cast (pIn) ); + osdThreadPrivate *p = (osdThreadPrivate *) id; + BOOL stat = TlsFree (p->key); assert (stat); } -#else /* ifdef __cplusplus */ - epicsShareFunc INLINE void epicsShareAPI threadPrivateSet (threadVarId id, void *pVal) { struct osdThreadPrivate *pPvt = (struct osdThreadPrivate *) id; @@ -52,6 +51,4 @@ epicsShareFunc INLINE void * epicsShareAPI threadPrivateGet (threadVarId id) return (void *) TlsGetValue (pPvt->key); } -#endif /* ifdef/else __cplusplus */ - #endif /* osdThreadh */