libCom/osi: Fix nesting for epicsThreadHooks, add WIN32 implementation, lock traversal

- call (generic) exit hook after calling the (specific) epicsExitCallAtThreadExits()
- for start hooks added as 1-2-3, run exit hooks in opposite order: 3-2-1
- add calls to hooks module to WIN32 osdThread.c
- add lock/unlock to hook list traversal
This commit is contained in:
Ralph Lange
2012-07-02 11:31:01 +02:00
parent d6648d4473
commit cfd8c0abde
5 changed files with 18 additions and 15 deletions

View File

@@ -166,8 +166,8 @@ threadWrapper (rtems_task_argument arg)
epicsThreadRunStartHooks(pthreadInfo);
(*v->funptr)(v->parm);
epicsThreadRunExitHooks(pthreadInfo);
epicsExitCallAtThreadExits ();
epicsThreadRunExitHooks(pthreadInfo);
taskVarLock ();
if (v->back)
v->back->forw = v->forw;

View File

@@ -16,13 +16,6 @@
*
*/
/* FIXME:
* The Windows implementation for thread hooks is still missing.
* epicsThreadHooksInit(); as part of the initialization
* epicsThreadRunStartHooks(pthreadInfo); from thread context before the user func runs
* epicsThreadRunExitHooks(pthreadInfo); from thread context after the user func exits
*/
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
@@ -233,6 +226,7 @@ static win32ThreadGlobal * fetchWin32ThreadGlobal ( void )
pWin32ThreadGlobal = 0;
return 0;
}
epicsThreadHooksInit();
InterlockedExchange ( & initCompleted, 1 );
@@ -503,6 +497,7 @@ static unsigned WINAPI epicsWin32ThreadEntry ( LPVOID lpParameter )
success = TlsSetValue ( pGbl->tlsIndexThreadLibraryEPICS, pParm );
if ( success ) {
epicsThreadRunStartHooks(pParm);
/* printf ( "starting thread %d\n", pParm->id ); */
( *pParm->funptr ) ( pParm->parm );
/* printf ( "terminating thread %d\n", pParm->id ); */
@@ -518,6 +513,8 @@ static unsigned WINAPI epicsWin32ThreadEntry ( LPVOID lpParameter )
epicsExitCallAtThreadExits ();
epicsThreadRunExitHooks(pParm);
/*
* CAUTION: !!!! the thread id might continue to be used after this thread exits !!!!
*/

View File

@@ -32,9 +32,11 @@ typedef struct epicsThreadHook {
static ELLLIST startHooks = ELLLIST_INIT;
static ELLLIST exitHooks = ELLLIST_INIT;
/* Locking could probably be avoided, if elllist implementation was using atomic ops */
static epicsMutexId hookLock;
static void addHook (ELLLIST *list, EPICS_THREAD_HOOK_ROUTINE func)
static void addHook (ELLLIST *list, EPICS_THREAD_HOOK_ROUTINE func, int atHead)
{
epicsThreadHook *pHook;
@@ -42,29 +44,33 @@ static void addHook (ELLLIST *list, EPICS_THREAD_HOOK_ROUTINE func)
if (!pHook) checkStatusOnceReturn(errno,"calloc","epicsThreadAddStartHook");
pHook->func = func;
epicsMutexLock(hookLock);
ellInsert(list, NULL, &pHook->node);
if (atHead)
ellInsert(list, NULL, &pHook->node);
else
ellAdd(list, &pHook->node);
epicsMutexUnlock(hookLock);
}
static void runHooks (ELLLIST *list, epicsThreadId id) {
epicsThreadHook *pHook;
/* As we're only ever inserting hooks at the head of the list, forward traversing is safe */
epicsMutexLock(hookLock);
pHook = (epicsThreadHook *) ellFirst(list);
while (pHook) {
pHook->func(id);
pHook = (epicsThreadHook *) ellNext(&pHook->node);
}
epicsMutexUnlock(hookLock);
}
epicsShareFunc void epicsShareAPI epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
addHook(&startHooks, hook);
addHook(&startHooks, hook, 0);
}
epicsShareFunc void epicsShareAPI epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
addHook(&exitHooks, hook);
addHook(&exitHooks, hook, 1);
}
epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void)

View File

@@ -378,8 +378,8 @@ static void * start_routine(void *arg)
(*pthreadInfo->createFunc)(pthreadInfo->createArg);
epicsThreadRunExitHooks(pthreadInfo);
epicsExitCallAtThreadExits ();
epicsThreadRunExitHooks(pthreadInfo);
free_threadInfo(pthreadInfo);
return(0);

View File

@@ -165,8 +165,8 @@ static void createFunction(EPICSTHREADFUNC func, void *parm)
papTSD = 0;
epicsThreadRunStartHooks(pthreadInfo);
(*func)(parm);
epicsThreadRunExitHooks(pthreadInfo);
epicsExitCallAtThreadExits ();
epicsThreadRunExitHooks(pthreadInfo);
free(papTSD);
taskVarDelete(tid,(int *)(char *)&papTSD);
}