From 8c323b2197fa1126fb1f77f9526b326e2a0c50c5 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 29 Jun 2012 17:54:38 +0200 Subject: [PATCH] libCom/osi: Add epicsThreadMap (calls user function for each thread) --- src/libCom/osi/epicsThread.h | 3 +++ src/libCom/osi/os/RTEMS/osdThread.c | 17 ++++++++++++++ src/libCom/osi/os/WIN32/osdThread.c | 33 +++++++++++++++++++++++++-- src/libCom/osi/os/posix/osdThread.c | 20 +++++++++++++++- src/libCom/osi/os/vxWorks/osdThread.c | 21 +++++++++++++++++ 5 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h index 6e6c30970..41547e87b 100644 --- a/src/libCom/osi/epicsThread.h +++ b/src/libCom/osi/epicsThread.h @@ -111,6 +111,9 @@ epicsShareFunc void epicsShareAPI epicsThreadRunExitHooks(epicsThreadId id); epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook; epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook; +/* Map func to all threads */ +epicsShareFunc void epicsShareAPI epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func); + typedef struct epicsThreadPrivateOSD * epicsThreadPrivateId; epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void); epicsShareFunc void epicsShareAPI epicsThreadPrivateDelete(epicsThreadPrivateId id); diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c index e6bb63f50..07842b3a3 100644 --- a/src/libCom/osi/os/RTEMS/osdThread.c +++ b/src/libCom/osi/os/RTEMS/osdThread.c @@ -677,6 +677,23 @@ void epicsThreadShow (epicsThreadId id, unsigned int level) fprintf(epicsGetStdout(),"*** Thread %x does not exist.\n", (unsigned int)id); } +void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func) +{ + struct taskVar *v; + + taskVarLock (); + /* + * Map tasks in the order of creation (backwards through list) + */ + for (v = taskVarHead ; v != NULL && v->forw != NULL ; v = v->forw) + continue; + while (v) { + func (v, arg); + v = v->back; + } + taskVarUnlock (); +} + void epicsThreadShowAll (unsigned int level) { struct taskVar *v; diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c index 86f7b7df7..a588e6237 100644 --- a/src/libCom/osi/os/WIN32/osdThread.c +++ b/src/libCom/osi/os/WIN32/osdThread.c @@ -16,6 +16,13 @@ * */ +/* 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 @@ -974,6 +981,28 @@ static void epicsThreadShowPrivate ( epicsThreadId id, unsigned level ) fprintf (epicsGetStdout(),"\n" ); } +/* + * epicsThreadMap () + */ +epicsShareFunc void epicsShareAPI epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE func ) +{ + win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); + win32ThreadParam * pParm; + + if ( ! pGbl ) { + return; + } + + EnterCriticalSection ( & pGbl->mutex ); + + for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList ); + pParm; pParm = ( win32ThreadParam * ) ellNext ( & pParm->node ) ) { + func ( ( epicsThreadId ) pParm ); + } + + LeaveCriticalSection ( & pGbl->mutex ); +} + /* * epicsThreadShowAll () */ @@ -987,9 +1016,9 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll ( unsigned level ) } EnterCriticalSection ( & pGbl->mutex ); - + epicsThreadShowPrivate ( 0, level ); - for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList ); + for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList ); pParm; pParm = ( win32ThreadParam * ) ellNext ( & pParm->node ) ) { epicsThreadShowPrivate ( ( epicsThreadId ) pParm, level ); } diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c index e3989e1bf..55e2c95d7 100644 --- a/src/libCom/osi/os/posix/osdThread.c +++ b/src/libCom/osi/os/posix/osdThread.c @@ -734,6 +734,25 @@ epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo, name[size-1] = '\0'; } +epicsShareFunc void epicsShareAPI epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func) +{ + epicsThreadOSD *pthreadInfo; + int status; + + epicsThreadInit(); + status = mutexLock(&listLock); + checkStatus(status, "pthread_mutex_lock epicsThreadMap"); + if (status) + return; + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); + while (pthreadInfo) { + func(pthreadInfo); + pthreadInfo = (epicsThreadOSD *)ellNext(&pthreadInfo->node); + } + status = pthread_mutex_unlock(&listLock); + checkStatus(status, "pthread_mutex_unlock epicsThreadMap"); +} + epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level) { epicsThreadOSD *pthreadInfo; @@ -784,7 +803,6 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsi if (!found) printf("Thread %#lx (%lu) not found.\n", (unsigned long)showThread, (unsigned long)showThread); } - epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void) { diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c index a69ddae3a..bfaef04df 100644 --- a/src/libCom/osi/os/vxWorks/osdThread.c +++ b/src/libCom/osi/os/vxWorks/osdThread.c @@ -42,6 +42,10 @@ static const unsigned stackSizeTable[epicsThreadStackBig+1] = {4000*ARCH_STACK_FACTOR, 6000*ARCH_STACK_FACTOR, 11000*ARCH_STACK_FACTOR}; +/* FIXME: this is the beta implementation of epicsThreadMap for vxWorks. See below. */ +#define ID_LIST_SIZE 2048 +static int taskIdList[ID_LIST_SIZE]; + /*The following forces atReboot to be loaded*/ extern int atRebootExtern; static struct pext { @@ -315,6 +319,23 @@ void epicsThreadGetName (epicsThreadId id, char *name, size_t size) name[size-1] = '\0'; } +epicsShareFunc void epicsShareAPI epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE func ) +{ +/* FIXME: add better vxWorks implementation that uses a dynamic taskIdList */ +/* Andrew says: + * use the vxWorks routine taskIdListGet(); + * that seems better, although there's no API to tell you how many tasks exist + * (I guess you could keep a count yourself if you register + * taskCreateHook and taskDeleteHook routines). */ + int noTasks; + int i; + + noTasks = taskIdListGet(taskIdList, ID_LIST_SIZE); + for (i = 0; i < noTasks; i++) { + func (i); + } +} + void epicsThreadShowAll(unsigned int level) { taskShow(0,2);