added thread once

This commit is contained in:
Jeff Hill
2000-03-02 00:00:01 +00:00
parent 99dc24ef61
commit a366afb80d
2 changed files with 172 additions and 44 deletions

View File

@@ -31,6 +31,7 @@ typedef struct {
HANDLE handle;
THREADFUNC funptr;
void *parm;
char *pName;
DWORD id;
char isSuspended;
} win32ThreadParam;
@@ -43,6 +44,83 @@ typedef struct osdThreadPrivate {
#define osdPriorityStateCount 7
static HANDLE win32ThreadGlobalMutex = 0;
static int win32ThreadInitOK = 0;
/*
* threadCleanupWIN32 ()
*/
static void threadCleanupWIN32 (void)
{
if (tlsIndexWIN32!=0xFFFFFFFF) {
TlsFree (tlsIndexWIN32);
tlsIndexWIN32 = 0xFFFFFFFF;
}
if (win32ThreadGlobalMutex) {
CloseHandle (win32ThreadGlobalMutex);
win32ThreadGlobalMutex = NULL;
}
}
/*
* threadInitWin32 ()
*/
static void threadInitWin32 ()
{
HANDLE win32ThreadGlobalMutexTmp;
DWORD status;
BOOL success;
int crtlStatus;
if (win32ThreadGlobalMutex) {
/* wait for init to complete */
status = WaitForSingleObject (win32ThreadGlobalMutex, INFINITE);
assert ( status == WAIT_OBJECT_0 );
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
return;
}
else {
win32ThreadGlobalMutexTmp = CreateMutex (NULL, TRUE, NULL);
if ( win32ThreadGlobalMutexTmp == 0 ) {
return;
}
/* not supported on W95, but the alternative requires assuming that pointer and integer are the same */
if (InterlockedCompareExchange ( (PVOID *) &win32ThreadGlobalMutex, (PVOID) win32ThreadGlobalMutexTmp, (PVOID)0 ) != 0) {
CloseHandle (win32ThreadGlobalMutexTmp);
/* wait for init to complete */
status = WaitForSingleObject (win32ThreadGlobalMutex, INFINITE);
assert ( status == WAIT_OBJECT_0 );
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
return;
}
}
if (tlsIndexWIN32==0xFFFFFFFF) {
tlsIndexWIN32 = TlsAlloc();
if (tlsIndexWIN32==0xFFFFFFFF) {
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
return;
}
}
crtlStatus = atexit (threadCleanupWIN32);
if (crtlStatus) {
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
return;
}
win32ThreadInitOK = TRUE;
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
}
/*
* threadGetOsdPriorityValue ()
*/
@@ -142,7 +220,6 @@ epicsShareFunc unsigned int epicsShareAPI threadGetStackSize (threadStackSizeCla
static DWORD WINAPI epicsWin32ThreadEntry (LPVOID lpParameter)
{
win32ThreadParam *pParm = (win32ThreadParam *) lpParameter;
HANDLE threadHandle;
BOOL stat;
stat = TlsSetValue (tlsIndexWIN32, pParm);
@@ -152,25 +229,17 @@ static DWORD WINAPI epicsWin32ThreadEntry (LPVOID lpParameter)
(*pParm->funptr) (pParm->parm);
threadHandle = pParm->handle;
free (pParm);
CloseHandle (threadHandle);
/*
* CAUTION: !!!! the thread id might continue to be used after its thread exits !!!!
*/
TlsSetValue (tlsIndexWIN32, 0);
CloseHandle (pParm->handle);
free (pParm->pName);
free (pParm);
return 1;
}
/*
* freeThreadLocalStorageIndex ()
*/
static void freeThreadLocalStorageIndex (void)
{
if (tlsIndexWIN32!=0xFFFFFFFF) {
TlsFree (tlsIndexWIN32);
tlsIndexWIN32 = 0xFFFFFFFF;
}
}
/*
* threadCreate()
*/
@@ -182,26 +251,25 @@ epicsShareFunc threadId epicsShareAPI threadCreate (const char *pName,
DWORD wstat;
BOOL bstat;
if (tlsIndexWIN32==0xFFFFFFFF) {
tlsIndexWIN32 = TlsAlloc();
if (tlsIndexWIN32==0xFFFFFFFF) {
return 0;
}
else {
int status;
status = atexit (freeThreadLocalStorageIndex);
if (status) {
freeThreadLocalStorageIndex ();
return NULL;
}
if (!win32ThreadInitOK) {
threadInitWin32 ();
if (!win32ThreadInitOK) {
return NULL;
}
}
pParmWIN32 = malloc (sizeof(*pParmWIN32));
pParmWIN32 = malloc ( sizeof (*pParmWIN32) );
if (pParmWIN32==NULL) {
return NULL;
}
/* potential for fragmentation of pool here */
pParmWIN32->pName = malloc ( strlen (pName) + 1 );
if (!pParmWIN32->pName) {
free (pParmWIN32);
return NULL;
}
strcpy (pParmWIN32->pName, pName);
pParmWIN32->funptr = pFunc;
pParmWIN32->parm = pParm;
pParmWIN32->isSuspended = 0;
@@ -236,11 +304,18 @@ epicsShareFunc threadId epicsShareAPI threadCreate (const char *pName,
epicsShareFunc void epicsShareAPI threadSuspendSelf ()
{
win32ThreadParam *pParm = (win32ThreadParam *) TlsGetValue (tlsIndexWIN32);
BOOL success;
DWORD stat;
if (pParm) {
stat = WaitForSingleObject (win32ThreadGlobalMutex, INFINITE);
assert ( stat == WAIT_OBJECT_0 );
stat = SuspendThread ( pParm->handle );
pParm->isSuspended = 1;
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
}
else {
stat = SuspendThread ( GetCurrentThread () );
@@ -254,11 +329,19 @@ epicsShareFunc void epicsShareAPI threadSuspendSelf ()
epicsShareFunc void epicsShareAPI threadResume (threadId id)
{
win32ThreadParam *pParm = (win32ThreadParam *) id;
BOOL success;
DWORD stat;
stat = WaitForSingleObject (win32ThreadGlobalMutex, INFINITE);
assert ( stat == WAIT_OBJECT_0 );
stat = ResumeThread ( pParm->handle );
assert (stat!=0xFFFFFFFF);
pParm->isSuspended = 0;
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
assert (stat!=0xFFFFFFFF);
}
/*
@@ -347,35 +430,73 @@ epicsShareFunc threadId epicsShareAPI threadGetIdSelf (void)
*/
epicsShareFunc const char * epicsShareAPI threadGetNameSelf (void)
{
/* not implemented (WFL) */
return (const char *) "";
win32ThreadParam *pParm = (win32ThreadParam *) TlsGetValue (tlsIndexWIN32);
if (pParm) {
return pParm->pName;
}
else {
return "anonymous";
}
}
/*
* threadGetName ()
*/
epicsShareFunc void epicsShareAPI threadGetName (threadId id, char *name, size_t size)
epicsShareFunc void epicsShareAPI threadGetName (threadId id, char *pName, size_t size)
{
/* not implemented (WFL) */
*name = '\0';
win32ThreadParam *pParm = (win32ThreadParam *) id;
if (size) {
size_t sizeMinusOne = size-1;
strncpy (pName, pParm->pName, sizeMinusOne);
pName [sizeMinusOne] = '\0';
}
}
/*
* threadShow ()
*/
epicsShareFunc void epicsShareAPI threadShow(void)
epicsShareFunc void epicsShareAPI threadShow (void)
{
printf("threadShow not implemented\n");
win32ThreadParam *pParm = (win32ThreadParam *) TlsGetValue (tlsIndexWIN32);
if (pParm) {
printf ("thread \"%s\" HANDLE=%p func=%p parm=%p %s %d\n",
pParm->pName, pParm->handle, pParm->funptr, pParm->parm,
pParm->isSuspended?"suspended":"running", pParm->id);
}
else {
printf ("thread was not created by threadCreate()\n");
}
}
epicsShareFunc void epicsShareAPI threadOnce(
/*
* threadOnce ()
*/
epicsShareFunc void epicsShareAPI threadOnceOsd (
threadOnceId *id, void (*func)(void *), void *arg)
{
printf("threadOnce not implemented\n");
cantProceed("threadOnce");
win32ThreadParam *pParm = (win32ThreadParam *) id;
BOOL success;
DWORD stat;
stat = WaitForSingleObject (win32ThreadGlobalMutex, INFINITE);
assert ( stat == WAIT_OBJECT_0 );
if (!*id) {
*id = 1;
(*func) (arg);
}
success = ReleaseMutex (win32ThreadGlobalMutex);
assert (success);
}
/*
* threadPrivateCreate ()
*/
epicsShareFunc threadPrivateId epicsShareAPI threadPrivateCreate ()
{
osdThreadPrivate *p = (osdThreadPrivate *) malloc (sizeof (*p));
@@ -389,13 +510,20 @@ epicsShareFunc threadPrivateId epicsShareAPI threadPrivateCreate ()
return (threadPrivateId) p;
}
/*
* threadPrivateDelete ()
*/
epicsShareFunc void epicsShareAPI threadPrivateDelete (threadPrivateId id)
{
osdThreadPrivate *p = (osdThreadPrivate *) id;
BOOL stat = TlsFree (p->key);
assert (stat);
free (p);
}
/*
* threadPrivateSet ()
*/
epicsShareFunc void epicsShareAPI threadPrivateSet (threadPrivateId id, void *pVal)
{
struct osdThreadPrivate *pPvt = (struct osdThreadPrivate *) id;
@@ -403,6 +531,9 @@ epicsShareFunc void epicsShareAPI threadPrivateSet (threadPrivateId id, void *pV
assert (stat);
}
/*
* threadPrivateGet ()
*/
epicsShareFunc void * epicsShareAPI threadPrivateGet (threadPrivateId id)
{
struct osdThreadPrivate *pPvt = (struct osdThreadPrivate *) id;

View File

@@ -2,8 +2,5 @@
#ifndef osdThreadh
#define osdThreadh
typedef int threadOnceId;
#define OSITHREAD_ONCE_INIT 0
#endif /* osdThreadh */