From cfd8c0abde997990c7d66274f3a2f543bc2668df Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 2 Jul 2012 11:31:01 +0200 Subject: [PATCH] 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 --- src/libCom/osi/os/RTEMS/osdThread.c | 2 +- src/libCom/osi/os/WIN32/osdThread.c | 11 ++++------- src/libCom/osi/os/default/osdThreadHooks.c | 16 +++++++++++----- src/libCom/osi/os/posix/osdThread.c | 2 +- src/libCom/osi/os/vxWorks/osdThread.c | 2 +- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c index 07842b3a3..d6a94ad4a 100644 --- a/src/libCom/osi/os/RTEMS/osdThread.c +++ b/src/libCom/osi/os/RTEMS/osdThread.c @@ -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; diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c index a588e6237..c66d9e606 100644 --- a/src/libCom/osi/os/WIN32/osdThread.c +++ b/src/libCom/osi/os/WIN32/osdThread.c @@ -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 #include #include @@ -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 !!!! */ diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c index c2cadeabf..9dc99e95e 100644 --- a/src/libCom/osi/os/default/osdThreadHooks.c +++ b/src/libCom/osi/os/default/osdThreadHooks.c @@ -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) diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c index 1d88cfba8..8734106f4 100644 --- a/src/libCom/osi/os/posix/osdThread.c +++ b/src/libCom/osi/os/posix/osdThread.c @@ -378,8 +378,8 @@ static void * start_routine(void *arg) (*pthreadInfo->createFunc)(pthreadInfo->createArg); - epicsThreadRunExitHooks(pthreadInfo); epicsExitCallAtThreadExits (); + epicsThreadRunExitHooks(pthreadInfo); free_threadInfo(pthreadInfo); return(0); diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c index 7c996b0e6..f782f389c 100644 --- a/src/libCom/osi/os/vxWorks/osdThread.c +++ b/src/libCom/osi/os/vxWorks/osdThread.c @@ -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); }