From 222ea314b0af8a8053b3b25d900cb883ad42ba55 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Thu, 28 Jun 2012 18:12:26 +0200
Subject: [PATCH 01/15] Add thread hooks to epicsThread that are called when a
thread starts or exits - add Linux implementation that + sets the system
command name to the EPICS thread name + retrieves the Linux LWP ID and
prints it instead of the posix thread ID in show commands
---
src/libCom/osi/Makefile | 2 +
src/libCom/osi/os/Linux/osdThread.h | 58 +++++++++++++++
src/libCom/osi/os/Linux/osdThreadExtra.c | 62 +++++++++++++++
src/libCom/osi/os/default/osdThreadExtra.c | 15 ++++
src/libCom/osi/os/default/osdThreadHooks.c | 87 ++++++++++++++++++++++
src/libCom/osi/os/posix/osdThread.c | 50 ++-----------
src/libCom/osi/os/posix/osdThread.h | 32 +++++++-
src/libCom/osi/os/posix/osdThreadExtra.c | 42 +++++++++++
8 files changed, 304 insertions(+), 44 deletions(-)
create mode 100644 src/libCom/osi/os/Linux/osdThread.h
create mode 100644 src/libCom/osi/os/Linux/osdThreadExtra.c
create mode 100644 src/libCom/osi/os/default/osdThreadExtra.c
create mode 100644 src/libCom/osi/os/default/osdThreadHooks.c
create mode 100644 src/libCom/osi/os/posix/osdThreadExtra.c
diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile
index 989784685..e22091712 100644
--- a/src/libCom/osi/Makefile
+++ b/src/libCom/osi/Makefile
@@ -104,6 +104,8 @@ THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
Com_SRCS += osdThread.c
+Com_SRCS += osdThreadExtra.c
+Com_SRCS += osdThreadHooks.c
Com_SRCS += osdMutex.c
Com_SRCS += osdEvent.c
Com_SRCS += osdTime.cpp
diff --git a/src/libCom/osi/os/Linux/osdThread.h b/src/libCom/osi/os/Linux/osdThread.h
new file mode 100644
index 000000000..52637b16f
--- /dev/null
+++ b/src/libCom/osi/os/Linux/osdThread.h
@@ -0,0 +1,58 @@
+/*************************************************************************\
+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* National Laboratory.
+* Copyright (c) 2002 The Regents of the University of California, as
+* Operator of Los Alamos National Laboratory.
+* EPICS BASE Versions 3.13.7
+* and higher are distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+#ifndef osdThreadh
+#define osdThreadh
+
+#include
+
+#include "shareLib.h"
+#include "ellLib.h"
+#include "epicsEvent.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct epicsThreadOSD {
+ ELLNODE node;
+ pthread_t tid;
+ pid_t lwpId;
+ pthread_attr_t attr;
+ struct sched_param schedParam;
+ EPICSTHREADFUNC createFunc;
+ void *createArg;
+ epicsEventId suspendEvent;
+ int isSuspended;
+ int isEpicsThread;
+ int isFifoScheduled;
+ int isOnThreadList;
+ unsigned int osiPriority;
+ char name[1]; /* actually larger */
+} epicsThreadOSD;
+
+/* Hooks being called when a thread starts or exits */
+typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadOSD *pthreadInfo);
+epicsShareFunc void epicsThreadHooksInit();
+epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadOSD *pthreadInfo);
+epicsShareFunc void epicsThreadRunExitHooks(epicsThreadOSD *pthreadInfo);
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
+
+epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId(epicsThreadId id);
+
+epicsShareFunc void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* osdThreadh */
diff --git a/src/libCom/osi/os/Linux/osdThreadExtra.c b/src/libCom/osi/os/Linux/osdThreadExtra.c
new file mode 100644
index 000000000..d6cd5a164
--- /dev/null
+++ b/src/libCom/osi/os/Linux/osdThreadExtra.c
@@ -0,0 +1,62 @@
+/*************************************************************************\
+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* National Laboratory.
+* Copyright (c) 2002 The Regents of the University of California, as
+* Operator of Los Alamos National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/* Author: Marty Kraimer Date: 18JAN2000 */
+
+/* This differs from the posix implementation of epicsThread by:
+ * - printing the Linux LWP ID instead of the POSIX thread ID in the show routines
+ * - installing a default thread start hook, that sets the Linux thread name to the
+ * EPICS thread name to make it visible on OS level, and discovers the LWP ID */
+
+#include
+#include
+#include
+#include
+#include
+
+#define epicsExportSharedSymbols
+#include "epicsStdio.h"
+#include "ellLib.h"
+#include "epicsEvent.h"
+#include "epicsThread.h"
+
+void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
+{
+ if(!pthreadInfo) {
+ fprintf(epicsGetStdout()," NAME EPICS ID "
+ "LWP ID OSIPRI OSSPRI STATE\n");
+ } else {
+ struct sched_param param;
+ int policy;
+ int priority = 0;
+
+ if(pthreadInfo->tid) {
+ int status;
+ status = pthread_getschedparam(pthreadInfo->tid,&policy,¶m);
+ if(!status) priority = param.sched_priority;
+ }
+ fprintf(epicsGetStdout(),"%16.16s %12p %8lu %3d%8d %8.8s\n",
+ pthreadInfo->name,(void *)
+ pthreadInfo,(unsigned long)pthreadInfo->lwpId,
+ pthreadInfo->osiPriority,priority,
+ pthreadInfo->isSuspended?"SUSPEND":"OK");
+ }
+}
+
+static void thread_hook(epicsThreadOSD *pthreadInfo)
+{
+ /* Set the name of the thread's process. Limited to 16 characters. */
+ char comm[16];
+ snprintf(comm, sizeof(comm), "%s", pthreadInfo->name);
+ prctl(PR_SET_NAME, comm, 0l, 0l, 0l);
+ pthreadInfo->lwpId = syscall(SYS_gettid);
+}
+
+EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook = thread_hook;
+EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
diff --git a/src/libCom/osi/os/default/osdThreadExtra.c b/src/libCom/osi/os/default/osdThreadExtra.c
new file mode 100644
index 000000000..bc5571e4a
--- /dev/null
+++ b/src/libCom/osi/os/default/osdThreadExtra.c
@@ -0,0 +1,15 @@
+/*************************************************************************\
+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* National Laboratory.
+* Copyright (c) 2002 The Regents of the University of California, as
+* Operator of Los Alamos National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/* Author: Ralph Lange Date: 26 Jun 2012 */
+
+/* Null default thread hooks for all platforms that do not do anything special */
+
+EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
new file mode 100644
index 000000000..b553cc160
--- /dev/null
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -0,0 +1,87 @@
+/*************************************************************************\
+* Copyright (c) 2012 Helmholtz-Zentrum Berlin
+* fuer Materialien und Energie GmbH.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/* Author: Ralph Lange Date: 28 Jun 2012 */
+
+/* Secure hooks for epicsThread */
+
+#include
+#include
+#include
+#include
+
+#define epicsExportSharedSymbols
+#include "ellLib.h"
+#include "epicsMutex.h"
+#include "epicsThread.h"
+
+#define checkStatusOnceReturn(status, message, method) \
+if((status)) { \
+ fprintf(stderr,"%s error %s\n",(message),strerror((status))); \
+ fprintf(stderr," %s\n",(method)); \
+ return; }
+
+typedef struct epicsThreadHook {
+ ELLNODE node;
+ EPICS_THREAD_HOOK_ROUTINE func;
+} epicsThreadHook;
+
+static ELLLIST startHooks;
+static ELLLIST exitHooks;
+static epicsMutexId hookLock;
+
+static void addHook (ELLLIST *list, EPICS_THREAD_HOOK_ROUTINE func)
+{
+ epicsThreadHook *pHook;
+
+ pHook = calloc(1, sizeof(epicsThreadHook));
+ if (!pHook) checkStatusOnceReturn(errno,"calloc","epicsThreadAddStartHook");
+ pHook->func = func;
+ epicsMutexLock(hookLock);
+ ellInsert(list, NULL, &pHook->node);
+ epicsMutexUnlock(hookLock);
+}
+
+static void runHooks (ELLLIST *list, epicsThreadOSD *pthreadInfo) {
+ epicsThreadHook *pHook;
+
+ /* As we're only ever inserting hooks at the head of the list, forward traversing is safe */
+ pHook = (epicsThreadHook *) ellFirst(list);
+ while (pHook) {
+ pHook->func(pthreadInfo);
+ pHook = (epicsThreadHook *) ellNext(&pHook->node);
+ }
+}
+
+void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE func)
+{
+ addHook(&startHooks, func);
+}
+
+void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE func)
+{
+ addHook(&exitHooks, func);
+}
+
+void epicsThreadHooksInit()
+{
+ hookLock = epicsMutexMustCreate();
+ ellInit(&startHooks);
+ ellInit(&exitHooks);
+ if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
+ if (epicsThreadDefaultExitHook) epicsThreadAddExitHook(epicsThreadDefaultExitHook);
+}
+
+void epicsThreadRunStartHooks(epicsThreadOSD *pthreadInfo)
+{
+ runHooks(&startHooks, pthreadInfo);
+}
+
+void epicsThreadRunExitHooks(epicsThreadOSD *pthreadInfo)
+{
+ runHooks(&exitHooks, pthreadInfo);
+}
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index 3c8844f70..e3989e1bf 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -57,22 +57,6 @@ typedef struct commonAttr{
int schedPolicy;
} commonAttr;
-typedef struct epicsThreadOSD {
- ELLNODE node;
- pthread_t tid;
- pthread_attr_t attr;
- struct sched_param schedParam;
- EPICSTHREADFUNC createFunc;
- void *createArg;
- epicsEventId suspendEvent;
- int isSuspended;
- int isEpicsThread;
- int isFifoScheduled;
- int isOnThreadList;
- unsigned int osiPriority;
- char name[1]; /* actually larger */
-} epicsThreadOSD;
-
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
typedef struct {
int min_pri, max_pri;
@@ -366,6 +350,7 @@ static void once(void)
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadInit");
status = atexit(epicsExitCallAtExits);
checkStatusOnce(status,"atexit");
+ epicsThreadHooksInit();
epicsThreadOnceCalled = 1;
}
@@ -375,7 +360,7 @@ static void * start_routine(void *arg)
int status;
int oldtype;
sigset_t blockAllSig;
-
+
sigfillset(&blockAllSig);
pthread_sigmask(SIG_SETMASK,&blockAllSig,NULL);
status = pthread_setspecific(getpthreadInfo,arg);
@@ -388,9 +373,11 @@ static void * start_routine(void *arg)
pthreadInfo->isOnThreadList = 1;
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","start_routine");
+ epicsThreadRunStartHooks(pthreadInfo);
(*pthreadInfo->createFunc)(pthreadInfo->createArg);
+ epicsThreadRunExitHooks(pthreadInfo);
epicsExitCallAtThreadExits ();
free_threadInfo(pthreadInfo);
@@ -747,29 +734,6 @@ epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo,
name[size-1] = '\0';
}
-static void showThreadInfo(epicsThreadOSD *pthreadInfo,unsigned int level)
-{
- if(!pthreadInfo) {
- fprintf(epicsGetStdout()," NAME EPICS ID "
- "PTHREAD ID OSIPRI OSSPRI STATE\n");
- } else {
- struct sched_param param;
- int policy;
- int priority = 0;
-
- if(pthreadInfo->tid) {
- int status;
- status = pthread_getschedparam(pthreadInfo->tid,&policy,¶m);
- if(!status) priority = param.sched_priority;
- }
- fprintf(epicsGetStdout(),"%16.16s %12p %12lu %3d%8d %8.8s\n",
- pthreadInfo->name,(void *)
- pthreadInfo,(unsigned long)pthreadInfo->tid,
- pthreadInfo->osiPriority,priority,
- pthreadInfo->isSuspended?"SUSPEND":"OK");
- }
-}
-
epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level)
{
epicsThreadOSD *pthreadInfo;
@@ -783,7 +747,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level)
return;
pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
while(pthreadInfo) {
- showThreadInfo(pthreadInfo,level);
+ epicsShowThreadInfo(pthreadInfo,level);
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
status = pthread_mutex_unlock(&listLock);
@@ -798,7 +762,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsi
epicsThreadInit();
if(!showThread) {
- showThreadInfo(0,level);
+ epicsShowThreadInfo(0,level);
return;
}
status = mutexLock(&listLock);
@@ -810,7 +774,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsi
if (((epicsThreadId)pthreadInfo == showThread)
|| ((epicsThreadId)pthreadInfo->tid == showThread)) {
found = 1;
- showThreadInfo(pthreadInfo,level);
+ epicsShowThreadInfo(pthreadInfo,level);
}
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
diff --git a/src/libCom/osi/os/posix/osdThread.h b/src/libCom/osi/os/posix/osdThread.h
index 99cfe319a..6ce223e6e 100644
--- a/src/libCom/osi/os/posix/osdThread.h
+++ b/src/libCom/osi/os/posix/osdThread.h
@@ -13,12 +13,42 @@
#include
#include "shareLib.h"
+#include "ellLib.h"
+#include "epicsEvent.h"
#ifdef __cplusplus
extern "C" {
#endif
-epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId ( epicsThreadId id );
+typedef struct epicsThreadOSD {
+ ELLNODE node;
+ pthread_t tid;
+ pthread_attr_t attr;
+ struct sched_param schedParam;
+ EPICSTHREADFUNC createFunc;
+ void *createArg;
+ epicsEventId suspendEvent;
+ int isSuspended;
+ int isEpicsThread;
+ int isFifoScheduled;
+ int isOnThreadList;
+ unsigned int osiPriority;
+ char name[1]; /* actually larger */
+} epicsThreadOSD;
+
+/* Hooks being called when a thread starts or exits */
+typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadOSD *pthreadInfo);
+epicsShareFunc void epicsThreadHooksInit();
+epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadOSD *pthreadInfo);
+epicsShareFunc void epicsThreadRunExitHooks(epicsThreadOSD *pthreadInfo);
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
+
+epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId(epicsThreadId id);
+
+epicsShareFunc void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
#ifdef __cplusplus
}
diff --git a/src/libCom/osi/os/posix/osdThreadExtra.c b/src/libCom/osi/os/posix/osdThreadExtra.c
new file mode 100644
index 000000000..93a149307
--- /dev/null
+++ b/src/libCom/osi/os/posix/osdThreadExtra.c
@@ -0,0 +1,42 @@
+/*************************************************************************\
+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* National Laboratory.
+* Copyright (c) 2002 The Regents of the University of California, as
+* Operator of Los Alamos National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/* Author: Marty Kraimer Date: 18JAN2000 */
+
+/* This is part of the posix implementation of epicsThread */
+
+#define epicsExportSharedSymbols
+#include "epicsStdio.h"
+#include "ellLib.h"
+#include "epicsEvent.h"
+#include "epicsThread.h"
+
+void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
+{
+ if(!pthreadInfo) {
+ fprintf(epicsGetStdout()," NAME EPICS ID "
+ "PTHREAD ID OSIPRI OSSPRI STATE\n");
+ } else {
+ struct sched_param param;
+ int policy;
+ int priority = 0;
+
+ if(pthreadInfo->tid) {
+ int status;
+ status = pthread_getschedparam(pthreadInfo->tid,&policy,¶m);
+ if(!status) priority = param.sched_priority;
+ }
+ fprintf(epicsGetStdout(),"%16.16s %12p %12lu %3d%8d %8.8s\n",
+ pthreadInfo->name,(void *)
+ pthreadInfo,(unsigned long)pthreadInfo->tid,
+ pthreadInfo->osiPriority,priority,
+ pthreadInfo->isSuspended?"SUSPEND":"OK");
+ }
+}
+
From 803777329c0a28bbd8182dbb4a5943db6ab0553a Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Fri, 29 Jun 2012 11:15:47 +0200
Subject: [PATCH 02/15] Cleanup of epicsThread hooks - move declarations to
epicsThread.h, use epicsThreadId type - use static elllist initializer for
static lists
---
src/libCom/osi/epicsThread.h | 10 ++++++++++
src/libCom/osi/os/Linux/osdThread.h | 10 ----------
src/libCom/osi/os/default/osdThreadHooks.c | 20 +++++++++-----------
src/libCom/osi/os/posix/osdThread.h | 10 ----------
4 files changed, 19 insertions(+), 31 deletions(-)
diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h
index fa0a6bd70..6e6c30970 100644
--- a/src/libCom/osi/epicsThread.h
+++ b/src/libCom/osi/epicsThread.h
@@ -101,6 +101,16 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level);
epicsShareFunc void epicsShareAPI epicsThreadShow(
epicsThreadId id,unsigned int level);
+/* Hooks being called when a thread starts or exits */
+typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id);
+epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void);
+epicsShareFunc void epicsShareAPI epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsShareAPI epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsShareAPI epicsThreadRunStartHooks(epicsThreadId id);
+epicsShareFunc void epicsShareAPI epicsThreadRunExitHooks(epicsThreadId id);
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
+
typedef struct epicsThreadPrivateOSD * epicsThreadPrivateId;
epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void);
epicsShareFunc void epicsShareAPI epicsThreadPrivateDelete(epicsThreadPrivateId id);
diff --git a/src/libCom/osi/os/Linux/osdThread.h b/src/libCom/osi/os/Linux/osdThread.h
index 52637b16f..ebdd47659 100644
--- a/src/libCom/osi/os/Linux/osdThread.h
+++ b/src/libCom/osi/os/Linux/osdThread.h
@@ -37,16 +37,6 @@ typedef struct epicsThreadOSD {
char name[1]; /* actually larger */
} epicsThreadOSD;
-/* Hooks being called when a thread starts or exits */
-typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadOSD *pthreadInfo);
-epicsShareFunc void epicsThreadHooksInit();
-epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsThreadRunStartHooks(epicsThreadOSD *pthreadInfo);
-epicsShareFunc void epicsThreadRunExitHooks(epicsThreadOSD *pthreadInfo);
-epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
-epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
-
epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId(epicsThreadId id);
epicsShareFunc void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index b553cc160..52f42b5ad 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -30,8 +30,8 @@ typedef struct epicsThreadHook {
EPICS_THREAD_HOOK_ROUTINE func;
} epicsThreadHook;
-static ELLLIST startHooks;
-static ELLLIST exitHooks;
+static ELLLIST startHooks = ELLLIST_INIT;
+static ELLLIST exitHooks = ELLLIST_INIT;
static epicsMutexId hookLock;
static void addHook (ELLLIST *list, EPICS_THREAD_HOOK_ROUTINE func)
@@ -46,13 +46,13 @@ static void addHook (ELLLIST *list, EPICS_THREAD_HOOK_ROUTINE func)
epicsMutexUnlock(hookLock);
}
-static void runHooks (ELLLIST *list, epicsThreadOSD *pthreadInfo) {
+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 */
pHook = (epicsThreadHook *) ellFirst(list);
while (pHook) {
- pHook->func(pthreadInfo);
+ pHook->func(id);
pHook = (epicsThreadHook *) ellNext(&pHook->node);
}
}
@@ -67,21 +67,19 @@ void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE func)
addHook(&exitHooks, func);
}
-void epicsThreadHooksInit()
+void epicsThreadHooksInit(void)
{
hookLock = epicsMutexMustCreate();
- ellInit(&startHooks);
- ellInit(&exitHooks);
if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
if (epicsThreadDefaultExitHook) epicsThreadAddExitHook(epicsThreadDefaultExitHook);
}
-void epicsThreadRunStartHooks(epicsThreadOSD *pthreadInfo)
+void epicsThreadRunStartHooks(epicsThreadId id)
{
- runHooks(&startHooks, pthreadInfo);
+ runHooks(&startHooks, id);
}
-void epicsThreadRunExitHooks(epicsThreadOSD *pthreadInfo)
+void epicsThreadRunExitHooks(epicsThreadId id)
{
- runHooks(&exitHooks, pthreadInfo);
+ runHooks(&exitHooks, id);
}
diff --git a/src/libCom/osi/os/posix/osdThread.h b/src/libCom/osi/os/posix/osdThread.h
index 6ce223e6e..0885f9410 100644
--- a/src/libCom/osi/os/posix/osdThread.h
+++ b/src/libCom/osi/os/posix/osdThread.h
@@ -36,16 +36,6 @@ typedef struct epicsThreadOSD {
char name[1]; /* actually larger */
} epicsThreadOSD;
-/* Hooks being called when a thread starts or exits */
-typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadOSD *pthreadInfo);
-epicsShareFunc void epicsThreadHooksInit();
-epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsThreadRunStartHooks(epicsThreadOSD *pthreadInfo);
-epicsShareFunc void epicsThreadRunExitHooks(epicsThreadOSD *pthreadInfo);
-epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
-epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
-
epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId(epicsThreadId id);
epicsShareFunc void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
From 7e9f0484332737f180dde9c755167470ca76c52a Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Fri, 29 Jun 2012 11:22:48 +0200
Subject: [PATCH 03/15] Add decorations to epicsThreadHooks.c
---
src/libCom/osi/os/default/osdThreadHooks.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index 52f42b5ad..8fddfa1e1 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -57,29 +57,29 @@ static void runHooks (ELLLIST *list, epicsThreadId id) {
}
}
-void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE func)
+epicsShareFunc void epicsShareAPI epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
- addHook(&startHooks, func);
+ addHook(&startHooks, hook);
}
-void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE func)
+epicsShareFunc void epicsShareAPI epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
- addHook(&exitHooks, func);
+ addHook(&exitHooks, hook);
}
-void epicsThreadHooksInit(void)
+epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void)
{
hookLock = epicsMutexMustCreate();
if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
if (epicsThreadDefaultExitHook) epicsThreadAddExitHook(epicsThreadDefaultExitHook);
}
-void epicsThreadRunStartHooks(epicsThreadId id)
+epicsShareFunc void epicsShareAPI epicsThreadRunStartHooks(epicsThreadId id)
{
runHooks(&startHooks, id);
}
-void epicsThreadRunExitHooks(epicsThreadId id)
+epicsShareFunc void epicsShareAPI epicsThreadRunExitHooks(epicsThreadId id)
{
runHooks(&exitHooks, id);
}
From 1f5376b30b237a0824727a3d66b6577b87965548 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Fri, 29 Jun 2012 14:49:24 +0200
Subject: [PATCH 04/15] libCom/osi: Add RTEMS and vxWorks implementation for
epicsThreadHooks
---
src/libCom/osi/os/RTEMS/osdThread.c | 3 +++
src/libCom/osi/os/default/osdThreadHooks.c | 8 +++++---
src/libCom/osi/os/vxWorks/osdThread.c | 3 +++
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c
index 7fa541bfd..e6bb63f50 100644
--- a/src/libCom/osi/os/RTEMS/osdThread.c
+++ b/src/libCom/osi/os/RTEMS/osdThread.c
@@ -164,7 +164,9 @@ threadWrapper (rtems_task_argument arg)
{
struct taskVar *v = (struct taskVar *)arg;
+ epicsThreadRunStartHooks(pthreadInfo);
(*v->funptr)(v->parm);
+ epicsThreadRunExitHooks(pthreadInfo);
epicsExitCallAtThreadExits ();
taskVarLock ();
if (v->back)
@@ -235,6 +237,7 @@ epicsThreadInit (void)
taskVarMutex = epicsMutexMustCreate ();
rtems_task_ident (RTEMS_SELF, 0, &tid);
setThreadInfo (tid, "_main_", NULL, NULL);
+ epicsThreadHooksInit();
initialized = 1;
epicsThreadCreate ("ImsgDaemon", 99,
epicsThreadGetStackSize (epicsThreadStackSmall),
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index 8fddfa1e1..76e83d3ce 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -69,9 +69,11 @@ epicsShareFunc void epicsShareAPI epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTI
epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void)
{
- hookLock = epicsMutexMustCreate();
- if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
- if (epicsThreadDefaultExitHook) epicsThreadAddExitHook(epicsThreadDefaultExitHook);
+ if (!hookLock) {
+ hookLock = epicsMutexMustCreate();
+ if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
+ if (epicsThreadDefaultExitHook) epicsThreadAddExitHook(epicsThreadDefaultExitHook);
+ }
}
epicsShareFunc void epicsShareAPI epicsThreadRunStartHooks(epicsThreadId id)
diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c
index 09d451fab..a69ddae3a 100644
--- a/src/libCom/osi/os/vxWorks/osdThread.c
+++ b/src/libCom/osi/os/vxWorks/osdThread.c
@@ -88,6 +88,7 @@ static void epicsThreadInit(void)
static int lock = 0;
while(!vxTas(&lock)) taskDelay(1);
+ epicsThreadHooksInit();
if(epicsThreadOnceMutex==0) {
epicsThreadOnceMutex = semMCreate(
SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
@@ -157,7 +158,9 @@ static void createFunction(EPICSTHREADFUNC func, void *parm)
taskVarAdd(tid,(int *)(char *)&papTSD);
/*Make sure that papTSD is still 0 after that call to taskVarAdd*/
papTSD = 0;
+ epicsThreadRunStartHooks(pthreadInfo);
(*func)(parm);
+ epicsThreadRunExitHooks(pthreadInfo);
epicsExitCallAtThreadExits ();
free(papTSD);
taskVarDelete(tid,(int *)(char *)&papTSD);
From 8c323b2197fa1126fb1f77f9526b326e2a0c50c5 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Fri, 29 Jun 2012 17:54:38 +0200
Subject: [PATCH 05/15] 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);
From d6648d4473a828809b079c0368c9f2da101e2909 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Fri, 29 Jun 2012 18:12:07 +0200
Subject: [PATCH 06/15] libCom/osi: Add some copyrights for ITER
---
src/libCom/osi/epicsThread.h | 4 ++--
src/libCom/osi/os/Linux/osdThreadExtra.c | 1 +
src/libCom/osi/os/default/osdThreadExtra.c | 6 ++----
src/libCom/osi/os/default/osdThreadHooks.c | 4 ++--
src/libCom/osi/os/posix/osdThread.c | 1 +
src/libCom/osi/os/vxWorks/osdThread.c | 1 +
6 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h
index 41547e87b..ab08e3d87 100644
--- a/src/libCom/osi/epicsThread.h
+++ b/src/libCom/osi/epicsThread.h
@@ -3,8 +3,8 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* Copyright (c) 2012 ITER Organization
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef epicsThreadh
diff --git a/src/libCom/osi/os/Linux/osdThreadExtra.c b/src/libCom/osi/os/Linux/osdThreadExtra.c
index d6cd5a164..fc1d2d1df 100644
--- a/src/libCom/osi/os/Linux/osdThreadExtra.c
+++ b/src/libCom/osi/os/Linux/osdThreadExtra.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* Copyright (c) 2012 ITER Organization
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/src/libCom/osi/os/default/osdThreadExtra.c b/src/libCom/osi/os/default/osdThreadExtra.c
index bc5571e4a..31b3abac7 100644
--- a/src/libCom/osi/os/default/osdThreadExtra.c
+++ b/src/libCom/osi/os/default/osdThreadExtra.c
@@ -1,8 +1,6 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
+* Copyright (c) 2012 ITER Organization
+*
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index 76e83d3ce..c2cadeabf 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -1,6 +1,6 @@
/*************************************************************************\
-* Copyright (c) 2012 Helmholtz-Zentrum Berlin
-* fuer Materialien und Energie GmbH.
+* Copyright (c) 2012 ITER Organization
+*
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index 55e2c95d7..1d88cfba8 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* Copyright (c) 2012 ITER Organization
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c
index bfaef04df..7c996b0e6 100644
--- a/src/libCom/osi/os/vxWorks/osdThread.c
+++ b/src/libCom/osi/os/vxWorks/osdThread.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* Copyright (c) 2012 ITER Organization
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
From cfd8c0abde997990c7d66274f3a2f543bc2668df Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Mon, 2 Jul 2012 11:31:01 +0200
Subject: [PATCH 07/15] 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);
}
From 37e490d1b2b509d7996a33df1b47e20328f713b4 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Mon, 2 Jul 2012 14:21:39 +0200
Subject: [PATCH 08/15] libCom/osi: Make vxWorks implementation of
epicsThreadMap() safe and dynamic
---
src/libCom/osi/os/vxWorks/osdThread.c | 49 ++++++++++++++++++---------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c
index f782f389c..9e0e7b70e 100644
--- a/src/libCom/osi/os/vxWorks/osdThread.c
+++ b/src/libCom/osi/os/vxWorks/osdThread.c
@@ -43,9 +43,11 @@
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];
+/* Table and lock for epicsThreadMap() */
+#define ID_LIST_CHUNK 512
+static int *taskIdList = 0;
+int taskIdListSize = 0;
+static SEM_ID epicsThreadListMutex = 0;
/*The following forces atReboot to be loaded*/
extern int atRebootExtern;
@@ -88,17 +90,25 @@ static int getOssPriorityValue(unsigned int osiPriority)
}
}
+static void mutexInit(SEM_ID lock)
+{
+ if (lock == 0) {
+ lock = semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
+ assert(lock);
+ }
+}
+
static void epicsThreadInit(void)
{
static int lock = 0;
while(!vxTas(&lock)) taskDelay(1);
epicsThreadHooksInit();
- if(epicsThreadOnceMutex==0) {
- epicsThreadOnceMutex = semMCreate(
- SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
- assert(epicsThreadOnceMutex);
- }
+ mutexInit(epicsThreadOnceMutex);
+ mutexInit(epicsThreadListMutex);
+ taskIdList = calloc(ID_LIST_CHUNK, sizeof(int));
+ assert(taskIdList);
+ taskIdListSize = ID_LIST_CHUNK;
lock = 0;
}
@@ -322,19 +332,26 @@ void epicsThreadGetName (epicsThreadId id, char *name, size_t size)
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 noTasks = 0;
int i;
+ int result;
- noTasks = taskIdListGet(taskIdList, ID_LIST_SIZE);
+ result = semTake(epicsThreadListMutex, WAIT_FOREVER);
+ assert(result == OK);
+ noTasks = taskIdListGet(taskIdList, taskIdListSize);
+ while (noTasks == 0) {
+ noTasks = taskIdListGet(taskIdList, taskIdListSize);
+ if (noTasks == taskIdListSize) {
+ taskIdList = realloc(taskIdList, (taskIdListSize+ID_LIST_CHUNK)*sizeof(int));
+ assert(taskIdList);
+ taskIdListSize += ID_LIST_CHUNK;
+ noTasks = 0;
+ }
+ }
for (i = 0; i < noTasks; i++) {
func (i);
}
+ semGive(epicsThreadListMutex);
}
void epicsThreadShowAll(unsigned int level)
From da91893ec24676c478946043a20c5cceb74b40f2 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Mon, 2 Jul 2012 18:18:54 +0200
Subject: [PATCH 09/15] libCom/test: Add test for epicsThreadHooks
---
src/libCom/test/Makefile | 5 ++
src/libCom/test/epicsThreadHooksTest.c | 115 +++++++++++++++++++++++++
2 files changed, 120 insertions(+)
create mode 100644 src/libCom/test/epicsThreadHooksTest.c
diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile
index f38b01dbf..659b3fcd0 100644
--- a/src/libCom/test/Makefile
+++ b/src/libCom/test/Makefile
@@ -89,6 +89,11 @@ epicsThreadPrivateTest_SRCS += epicsThreadPrivateTest.cpp
testHarness_SRCS += epicsThreadPrivateTest.cpp
TESTS += epicsThreadPrivateTest
+TESTPROD_HOST += epicsThreadHooksTest
+epicsThreadHooksTest_SRCS += epicsThreadHooksTest.c
+testHarness_SRCS += epicsThreadHooksTest.c
+TESTS += epicsThreadHooksTest
+
TESTPROD_HOST += epicsExitTest
epicsExitTest_SRCS += epicsExitTest.c
testHarness_SRCS += epicsExitTest.c
diff --git a/src/libCom/test/epicsThreadHooksTest.c b/src/libCom/test/epicsThreadHooksTest.c
new file mode 100644
index 000000000..cb13758b3
--- /dev/null
+++ b/src/libCom/test/epicsThreadHooksTest.c
@@ -0,0 +1,115 @@
+/*************************************************************************\
+* Copyright (c) 2012 ITER Organization
+*
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/* epicsThreadHooksTest.c */
+
+#include
+#include
+
+#include "epicsThread.h"
+#include "epicsExit.h"
+#include "errlog.h"
+#include "epicsUnitTest.h"
+#include "testMain.h"
+
+#define THREAD_NO 6
+#define HOOKS_NO 6
+
+epicsThreadPrivateId threadNo;
+static int order[THREAD_NO][HOOKS_NO];
+static int cnt[THREAD_NO];
+static int mine[THREAD_NO];
+static epicsThreadId tid[THREAD_NO];
+
+static int newThreadIndex(epicsThreadId id)
+{
+ int i = 0;
+ while (tid[i] != 0 && i < THREAD_NO) i++;
+ tid[i] = id;
+ return i;
+}
+
+static int findThreadIndex(epicsThreadId id)
+{
+ int i = 0;
+ while (tid[i] != id && i < THREAD_NO) i++;
+ return i;
+}
+
+static void startHook1 (epicsThreadId id)
+{
+ int no = newThreadIndex(id);
+ order[no][0] = cnt[no]++;
+}
+
+static void startHook2 (epicsThreadId id)
+{
+ int no = findThreadIndex(id);
+ order[no][1] = cnt[no]++;
+}
+
+static void atExitHook1 (void *arg)
+{
+ int no = findThreadIndex(epicsThreadGetIdSelf());
+ order[no][3] = cnt[no]++;
+}
+
+static void atExitHook2 (void *arg)
+{
+ int no = findThreadIndex(epicsThreadGetIdSelf());
+ order[no][2] = cnt[no]++;
+}
+
+static void exitHook1 (epicsThreadId id)
+{
+ int no = findThreadIndex(id);
+ order[no][5] = cnt[no]++;
+}
+
+static void exitHook2 (epicsThreadId id)
+{
+ int no = findThreadIndex(id);
+ order[no][4] = cnt[no]++;
+}
+
+static void my_thread (void *arg)
+{
+ int no = findThreadIndex(epicsThreadGetIdSelf());
+ mine[no] = 1;
+ epicsAtThreadExit(atExitHook1, NULL);
+ epicsAtThreadExit(atExitHook2, NULL);
+ epicsThreadSleep(0.1);
+}
+
+MAIN(epicsThreadHooksTest)
+{
+ int i;
+
+ testPlan(THREAD_NO-1);
+ epicsThreadAddStartHook(startHook1);
+ epicsThreadAddExitHook(exitHook1);
+ epicsThreadAddStartHook(startHook2);
+ epicsThreadAddExitHook(exitHook2);
+
+ for (i = 0; i < THREAD_NO-1; i++) {
+ char name[10];
+ sprintf(name, "t%d", (int) i);
+ epicsThreadCreate(name, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), my_thread, NULL);
+ }
+
+ epicsThreadSleep(1.0);
+
+ for (i = 0; i < THREAD_NO; i++) {
+ int ok = 1;
+ int j;
+ for (j = 0; j < HOOKS_NO; j++) {
+ if (mine[i] && order[i][j]!=j) ok = 0;
+ }
+ if (mine[i]) testOk(ok, "All %d hooks for task %d called in correct order", HOOKS_NO, (int)i);
+ }
+ return testDone();
+}
From 7c27c7c56d544b17b7a0ec29591e41b4efa6a463 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Mon, 2 Jul 2012 18:31:08 +0200
Subject: [PATCH 10/15] documentation: Add epicsThreadHooks info to RELEASE
NOTES
---
documentation/RELEASE_NOTES.html | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 139072f5d..9b78e72e0 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -15,6 +15,17 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.
Changes between 3.14.x and 3.15.0.x
+New API to hook into thread creation and deletion
+
+A hook API has been added allowing user-supplied functions to be called
+whenever a thread starts or exits. The calls are made from the thread's
+context, and can be used to control additional thread properties not handled
+inside EPICS base, e.g. setting the scheduling policy or CPU affinity (on SMP
+systems).
+
+The API also supports a mapping operation, calling a user-supplied function
+for every thread that is currently running.
+
New scan rate units
Scan rates defined in the menuScan.dbd file may now be specified in seconds,
From 0e6a01d56a1379c193f9c2dd918d2ddea02756cd Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Tue, 3 Jul 2012 11:16:09 +0200
Subject: [PATCH 11/15] libCom/osi: Streamline epicsThreadShowInfo functions
between implementations - epicsThreadShowInfo: private function to print
headers or task line, not in header file, using internal pointer type
---
src/libCom/osi/os/Linux/osdThread.h | 2 --
src/libCom/osi/os/Linux/osdThreadExtra.c | 2 +-
src/libCom/osi/os/RTEMS/osdThread.c | 16 +++++++---------
src/libCom/osi/os/WIN32/osdThread.c | 12 ++++++------
src/libCom/osi/os/posix/osdThread.c | 8 +++++---
src/libCom/osi/os/posix/osdThread.h | 2 --
src/libCom/osi/os/posix/osdThreadExtra.c | 2 +-
7 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/src/libCom/osi/os/Linux/osdThread.h b/src/libCom/osi/os/Linux/osdThread.h
index ebdd47659..eb0a60ede 100644
--- a/src/libCom/osi/os/Linux/osdThread.h
+++ b/src/libCom/osi/os/Linux/osdThread.h
@@ -39,8 +39,6 @@ typedef struct epicsThreadOSD {
epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId(epicsThreadId id);
-epicsShareFunc void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/libCom/osi/os/Linux/osdThreadExtra.c b/src/libCom/osi/os/Linux/osdThreadExtra.c
index fc1d2d1df..aa830c6ee 100644
--- a/src/libCom/osi/os/Linux/osdThreadExtra.c
+++ b/src/libCom/osi/os/Linux/osdThreadExtra.c
@@ -27,7 +27,7 @@
#include "epicsEvent.h"
#include "epicsThread.h"
-void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
+void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
{
if(!pthreadInfo) {
fprintf(epicsGetStdout()," NAME EPICS ID "
diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c
index d6a94ad4a..13e2469f9 100644
--- a/src/libCom/osi/os/RTEMS/osdThread.c
+++ b/src/libCom/osi/os/RTEMS/osdThread.c
@@ -642,20 +642,18 @@ showInternalTaskInfo (rtems_id tid)
#endif
}
-static void
-epicsThreadShowHeader (void)
-{
- fprintf(epicsGetStdout()," PRIORITY\n");
- fprintf(epicsGetStdout()," ID EPICS RTEMS STATE WAIT NAME\n");
- fprintf(epicsGetStdout(),"+--------+-----------+--------+--------+---------------------+\n");
-}
-
static void
epicsThreadShowInfo (struct taskVar *v, unsigned int level)
{
+ if (!v) {
+ fprintf(epicsGetStdout()," PRIORITY\n");
+ fprintf(epicsGetStdout()," ID EPICS RTEMS STATE WAIT NAME\n");
+ fprintf(epicsGetStdout(),"+--------+-----------+--------+--------+---------------------+\n");
+ } else {
fprintf(epicsGetStdout(),"%9.8x", (int)v->id);
showInternalTaskInfo (v->id);
fprintf(epicsGetStdout()," %s\n", v->name);
+ }
}
void epicsThreadShow (epicsThreadId id, unsigned int level)
@@ -663,7 +661,7 @@ void epicsThreadShow (epicsThreadId id, unsigned int level)
struct taskVar *v;
if (!id) {
- epicsThreadShowHeader ();
+ epicsThreadShowInfo (NULL, level);
return;
}
taskVarLock ();
diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c
index c66d9e606..1acef7e52 100644
--- a/src/libCom/osi/os/WIN32/osdThread.c
+++ b/src/libCom/osi/os/WIN32/osdThread.c
@@ -951,9 +951,9 @@ static const char * epics_GetThreadPriorityAsString ( HANDLE thr )
}
/*
- * epicsThreadShowPrivate ()
+ * epicsThreadShowInfo ()
*/
-static void epicsThreadShowPrivate ( epicsThreadId id, unsigned level )
+static void epicsThreadShowInfo ( epicsThreadId id, unsigned level )
{
win32ThreadParam * pParm = ( win32ThreadParam * ) id;
@@ -1014,10 +1014,10 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll ( unsigned level )
EnterCriticalSection ( & pGbl->mutex );
- epicsThreadShowPrivate ( 0, level );
+ epicsThreadShowInfo ( 0, level );
for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList );
pParm; pParm = ( win32ThreadParam * ) ellNext ( & pParm->node ) ) {
- epicsThreadShowPrivate ( ( epicsThreadId ) pParm, level );
+ epicsThreadShowInfo ( ( epicsThreadId ) pParm, level );
}
LeaveCriticalSection ( & pGbl->mutex );
@@ -1028,8 +1028,8 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll ( unsigned level )
*/
epicsShareFunc void epicsShareAPI epicsThreadShow ( epicsThreadId id, unsigned level )
{
- epicsThreadShowPrivate ( 0, level );
- epicsThreadShowPrivate ( id, level );
+ epicsThreadShowInfo ( 0, level );
+ epicsThreadShowInfo ( id, level );
}
/*
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index 8734106f4..d1a0a2644 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -35,6 +35,8 @@
#include "epicsAssert.h"
#include "epicsExit.h"
+epicsShareFunc void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
+
static int mutexLock(pthread_mutex_t *id)
{
int status;
@@ -767,7 +769,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level)
return;
pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
while(pthreadInfo) {
- epicsShowThreadInfo(pthreadInfo,level);
+ epicsThreadShowInfo(pthreadInfo,level);
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
status = pthread_mutex_unlock(&listLock);
@@ -782,7 +784,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsi
epicsThreadInit();
if(!showThread) {
- epicsShowThreadInfo(0,level);
+ epicsThreadShowInfo(0,level);
return;
}
status = mutexLock(&listLock);
@@ -794,7 +796,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsi
if (((epicsThreadId)pthreadInfo == showThread)
|| ((epicsThreadId)pthreadInfo->tid == showThread)) {
found = 1;
- epicsShowThreadInfo(pthreadInfo,level);
+ epicsThreadShowInfo(pthreadInfo,level);
}
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
diff --git a/src/libCom/osi/os/posix/osdThread.h b/src/libCom/osi/os/posix/osdThread.h
index 0885f9410..ee6f6cd4d 100644
--- a/src/libCom/osi/os/posix/osdThread.h
+++ b/src/libCom/osi/os/posix/osdThread.h
@@ -38,8 +38,6 @@ typedef struct epicsThreadOSD {
epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId(epicsThreadId id);
-epicsShareFunc void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/libCom/osi/os/posix/osdThreadExtra.c b/src/libCom/osi/os/posix/osdThreadExtra.c
index 93a149307..9df3485af 100644
--- a/src/libCom/osi/os/posix/osdThreadExtra.c
+++ b/src/libCom/osi/os/posix/osdThreadExtra.c
@@ -17,7 +17,7 @@
#include "epicsEvent.h"
#include "epicsThread.h"
-void epicsShowThreadInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
+void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
{
if(!pthreadInfo) {
fprintf(epicsGetStdout()," NAME EPICS ID "
From e834832cda3f06d26e764d6eba00fc88d7033278 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Tue, 3 Jul 2012 13:20:01 +0200
Subject: [PATCH 12/15] libCom/osi: Don't decorate epicsThreadHook functions
with epicsShareAPI
---
src/libCom/osi/epicsThread.h | 12 ++++++------
src/libCom/osi/os/default/osdThreadHooks.c | 10 +++++-----
src/libCom/osi/os/posix/osdThread.c | 2 +-
src/libCom/osi/os/vxWorks/osdThread.c | 2 +-
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h
index ab08e3d87..56710be20 100644
--- a/src/libCom/osi/epicsThread.h
+++ b/src/libCom/osi/epicsThread.h
@@ -103,16 +103,16 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(
/* Hooks being called when a thread starts or exits */
typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id);
-epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void);
-epicsShareFunc void epicsShareAPI epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsShareAPI epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsShareAPI epicsThreadRunStartHooks(epicsThreadId id);
-epicsShareFunc void epicsShareAPI epicsThreadRunExitHooks(epicsThreadId id);
+epicsShareFunc void epicsThreadHooksInit(void);
+epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
+epicsShareFunc void 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);
+epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func);
typedef struct epicsThreadPrivateOSD * epicsThreadPrivateId;
epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void);
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index 9dc99e95e..c3a6a3fa8 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -63,17 +63,17 @@ static void runHooks (ELLLIST *list, epicsThreadId id) {
epicsMutexUnlock(hookLock);
}
-epicsShareFunc void epicsShareAPI epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
+epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
addHook(&startHooks, hook, 0);
}
-epicsShareFunc void epicsShareAPI epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook)
+epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
addHook(&exitHooks, hook, 1);
}
-epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void)
+epicsShareFunc void epicsThreadHooksInit(void)
{
if (!hookLock) {
hookLock = epicsMutexMustCreate();
@@ -82,12 +82,12 @@ epicsShareFunc void epicsShareAPI epicsThreadHooksInit(void)
}
}
-epicsShareFunc void epicsShareAPI epicsThreadRunStartHooks(epicsThreadId id)
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id)
{
runHooks(&startHooks, id);
}
-epicsShareFunc void epicsShareAPI epicsThreadRunExitHooks(epicsThreadId id)
+epicsShareFunc void epicsThreadRunExitHooks(epicsThreadId id)
{
runHooks(&exitHooks, id);
}
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index d1a0a2644..5653e5937 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -737,7 +737,7 @@ epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo,
name[size-1] = '\0';
}
-epicsShareFunc void epicsShareAPI epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func)
+epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func)
{
epicsThreadOSD *pthreadInfo;
int status;
diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c
index 9e0e7b70e..61f2145f1 100644
--- a/src/libCom/osi/os/vxWorks/osdThread.c
+++ b/src/libCom/osi/os/vxWorks/osdThread.c
@@ -330,7 +330,7 @@ void epicsThreadGetName (epicsThreadId id, char *name, size_t size)
name[size-1] = '\0';
}
-epicsShareFunc void epicsShareAPI epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE func )
+epicsShareFunc void epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE func )
{
int noTasks = 0;
int i;
From 7b47cad8e49a82402750183297eb50e8a1be8304 Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Tue, 3 Jul 2012 14:38:12 +0200
Subject: [PATCH 13/15] libCom/osi: Clean up epicsThreadHooks API - remove exit
hooks completely - remove non-public functions fom header files - add test
for epicsThreadMap - fix bugs in RTEMS and vxWorks implementation of
epicsThreadMap
---
src/libCom/osi/epicsThread.h | 9 +---
src/libCom/osi/os/Linux/osdThreadExtra.c | 3 +-
src/libCom/osi/os/RTEMS/osdThread.c | 7 +--
src/libCom/osi/os/WIN32/osdThread.c | 9 ++--
src/libCom/osi/os/default/osdThreadExtra.c | 6 ++-
src/libCom/osi/os/default/osdThreadHooks.c | 49 +++++------------
src/libCom/osi/os/posix/osdThread.c | 3 +-
src/libCom/osi/os/vxWorks/osdThread.c | 8 +--
src/libCom/test/epicsThreadHooksTest.c | 61 ++++++++++++----------
9 files changed, 69 insertions(+), 86 deletions(-)
diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h
index 56710be20..a94bd9c3b 100644
--- a/src/libCom/osi/epicsThread.h
+++ b/src/libCom/osi/epicsThread.h
@@ -101,17 +101,10 @@ epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level);
epicsShareFunc void epicsShareAPI epicsThreadShow(
epicsThreadId id,unsigned int level);
-/* Hooks being called when a thread starts or exits */
+/* Hooks called when a thread starts, map function called once for every thread */
typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id);
epicsShareFunc void epicsThreadHooksInit(void);
epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook);
-epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
-epicsShareFunc void epicsThreadRunExitHooks(epicsThreadId id);
-epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
-epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
-
-/* Map func to all threads */
epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func);
typedef struct epicsThreadPrivateOSD * epicsThreadPrivateId;
diff --git a/src/libCom/osi/os/Linux/osdThreadExtra.c b/src/libCom/osi/os/Linux/osdThreadExtra.c
index aa830c6ee..61a0ef2bd 100644
--- a/src/libCom/osi/os/Linux/osdThreadExtra.c
+++ b/src/libCom/osi/os/Linux/osdThreadExtra.c
@@ -27,6 +27,8 @@
#include "epicsEvent.h"
#include "epicsThread.h"
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+
void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
{
if(!pthreadInfo) {
@@ -60,4 +62,3 @@ static void thread_hook(epicsThreadOSD *pthreadInfo)
}
EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook = thread_hook;
-EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c
index 13e2469f9..70a014539 100644
--- a/src/libCom/osi/os/RTEMS/osdThread.c
+++ b/src/libCom/osi/os/RTEMS/osdThread.c
@@ -39,6 +39,8 @@
#include "osdInterrupt.h"
#include "epicsExit.h"
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
+
/*
* Per-task variables
*/
@@ -164,10 +166,9 @@ threadWrapper (rtems_task_argument arg)
{
struct taskVar *v = (struct taskVar *)arg;
- epicsThreadRunStartHooks(pthreadInfo);
+ epicsThreadRunStartHooks(v->id);
(*v->funptr)(v->parm);
epicsExitCallAtThreadExits ();
- epicsThreadRunExitHooks(pthreadInfo);
taskVarLock ();
if (v->back)
v->back->forw = v->forw;
@@ -686,7 +687,7 @@ void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func)
for (v = taskVarHead ; v != NULL && v->forw != NULL ; v = v->forw)
continue;
while (v) {
- func (v, arg);
+ func ((epicsThreadId)v->id);
v = v->back;
}
taskVarUnlock ();
diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c
index 1acef7e52..e9c573731 100644
--- a/src/libCom/osi/os/WIN32/osdThread.c
+++ b/src/libCom/osi/os/WIN32/osdThread.c
@@ -38,6 +38,8 @@
#include "ellLib.h"
#include "epicsExit.h"
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
+
void setThreadName ( DWORD dwThreadID, LPCSTR szThreadName );
static void threadCleanupWIN32 ( void );
@@ -226,7 +228,7 @@ static win32ThreadGlobal * fetchWin32ThreadGlobal ( void )
pWin32ThreadGlobal = 0;
return 0;
}
- epicsThreadHooksInit();
+ epicsThreadHooksInit ();
InterlockedExchange ( & initCompleted, 1 );
@@ -497,7 +499,7 @@ static unsigned WINAPI epicsWin32ThreadEntry ( LPVOID lpParameter )
success = TlsSetValue ( pGbl->tlsIndexThreadLibraryEPICS, pParm );
if ( success ) {
- epicsThreadRunStartHooks(pParm);
+ epicsThreadRunStartHooks ( ( epicsThreadId ) pParm );
/* printf ( "starting thread %d\n", pParm->id ); */
( *pParm->funptr ) ( pParm->parm );
/* printf ( "terminating thread %d\n", pParm->id ); */
@@ -512,9 +514,6 @@ 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/osdThreadExtra.c b/src/libCom/osi/os/default/osdThreadExtra.c
index 31b3abac7..311db013d 100644
--- a/src/libCom/osi/os/default/osdThreadExtra.c
+++ b/src/libCom/osi/os/default/osdThreadExtra.c
@@ -9,5 +9,9 @@
/* Null default thread hooks for all platforms that do not do anything special */
+#define epicsExportSharedSymbols
+#include "shareLib.h"
+
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+
EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
-EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultExitHook;
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index c3a6a3fa8..86f0113dd 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -19,6 +19,9 @@
#include "epicsMutex.h"
#include "epicsThread.h"
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+
#define checkStatusOnceReturn(status, message, method) \
if((status)) { \
fprintf(stderr,"%s error %s\n",(message),strerror((status))); \
@@ -31,63 +34,39 @@ typedef struct epicsThreadHook {
} 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, int atHead)
+epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
{
epicsThreadHook *pHook;
pHook = calloc(1, sizeof(epicsThreadHook));
if (!pHook) checkStatusOnceReturn(errno,"calloc","epicsThreadAddStartHook");
- pHook->func = func;
+ pHook->func = hook;
epicsMutexLock(hookLock);
- if (atHead)
- ellInsert(list, NULL, &pHook->node);
- else
- ellAdd(list, &pHook->node);
+ ellAdd(&startHooks, &pHook->node);
epicsMutexUnlock(hookLock);
}
-static void runHooks (ELLLIST *list, epicsThreadId id) {
- epicsThreadHook *pHook;
-
- epicsMutexLock(hookLock);
- pHook = (epicsThreadHook *) ellFirst(list);
- while (pHook) {
- pHook->func(id);
- pHook = (epicsThreadHook *) ellNext(&pHook->node);
- }
- epicsMutexUnlock(hookLock);
-}
-
-epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
-{
- addHook(&startHooks, hook, 0);
-}
-
-epicsShareFunc void epicsThreadAddExitHook(EPICS_THREAD_HOOK_ROUTINE hook)
-{
- addHook(&exitHooks, hook, 1);
-}
-
epicsShareFunc void epicsThreadHooksInit(void)
{
if (!hookLock) {
hookLock = epicsMutexMustCreate();
if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
- if (epicsThreadDefaultExitHook) epicsThreadAddExitHook(epicsThreadDefaultExitHook);
}
}
epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id)
{
- runHooks(&startHooks, id);
-}
+ epicsThreadHook *pHook;
-epicsShareFunc void epicsThreadRunExitHooks(epicsThreadId id)
-{
- runHooks(&exitHooks, id);
+ epicsMutexLock(hookLock);
+ pHook = (epicsThreadHook *) ellFirst(&startHooks);
+ while (pHook) {
+ pHook->func(id);
+ pHook = (epicsThreadHook *) ellNext(&pHook->node);
+ }
+ epicsMutexUnlock(hookLock);
}
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index 5653e5937..6eac4f8b8 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -36,6 +36,7 @@
#include "epicsExit.h"
epicsShareFunc void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
static int mutexLock(pthread_mutex_t *id)
{
@@ -381,8 +382,6 @@ static void * start_routine(void *arg)
(*pthreadInfo->createFunc)(pthreadInfo->createArg);
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 61f2145f1..7953c03ef 100644
--- a/src/libCom/osi/os/vxWorks/osdThread.c
+++ b/src/libCom/osi/os/vxWorks/osdThread.c
@@ -33,6 +33,8 @@
#include "vxLib.h"
#include "epicsExit.h"
+epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
+
#if CPU_FAMILY == MC680X0
#define ARCH_STACK_FACTOR 1
#elif CPU_FAMILY == SPARC
@@ -173,10 +175,9 @@ static void createFunction(EPICSTHREADFUNC func, void *parm)
taskVarAdd(tid,(int *)(char *)&papTSD);
/*Make sure that papTSD is still 0 after that call to taskVarAdd*/
papTSD = 0;
- epicsThreadRunStartHooks(pthreadInfo);
+ epicsThreadRunStartHooks((epicsThreadId)tid);
(*func)(parm);
epicsExitCallAtThreadExits ();
- epicsThreadRunExitHooks(pthreadInfo);
free(papTSD);
taskVarDelete(tid,(int *)(char *)&papTSD);
}
@@ -338,7 +339,6 @@ epicsShareFunc void epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE func )
result = semTake(epicsThreadListMutex, WAIT_FOREVER);
assert(result == OK);
- noTasks = taskIdListGet(taskIdList, taskIdListSize);
while (noTasks == 0) {
noTasks = taskIdListGet(taskIdList, taskIdListSize);
if (noTasks == taskIdListSize) {
@@ -349,7 +349,7 @@ epicsShareFunc void epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE func )
}
}
for (i = 0; i < noTasks; i++) {
- func (i);
+ func ((epicsThreadId)taskIdList[i]);
}
semGive(epicsThreadListMutex);
}
diff --git a/src/libCom/test/epicsThreadHooksTest.c b/src/libCom/test/epicsThreadHooksTest.c
index cb13758b3..ea5722ef7 100644
--- a/src/libCom/test/epicsThreadHooksTest.c
+++ b/src/libCom/test/epicsThreadHooksTest.c
@@ -12,18 +12,21 @@
#include "epicsThread.h"
#include "epicsExit.h"
+#include "epicsEvent.h"
#include "errlog.h"
#include "epicsUnitTest.h"
#include "testMain.h"
#define THREAD_NO 6
-#define HOOKS_NO 6
+#define HOOKS_NO 4
epicsThreadPrivateId threadNo;
static int order[THREAD_NO][HOOKS_NO];
static int cnt[THREAD_NO];
static int mine[THREAD_NO];
+static int called[THREAD_NO];
static epicsThreadId tid[THREAD_NO];
+epicsEventId shutdown[THREAD_NO];
static int newThreadIndex(epicsThreadId id)
{
@@ -40,18 +43,6 @@ static int findThreadIndex(epicsThreadId id)
return i;
}
-static void startHook1 (epicsThreadId id)
-{
- int no = newThreadIndex(id);
- order[no][0] = cnt[no]++;
-}
-
-static void startHook2 (epicsThreadId id)
-{
- int no = findThreadIndex(id);
- order[no][1] = cnt[no]++;
-}
-
static void atExitHook1 (void *arg)
{
int no = findThreadIndex(epicsThreadGetIdSelf());
@@ -64,52 +55,68 @@ static void atExitHook2 (void *arg)
order[no][2] = cnt[no]++;
}
-static void exitHook1 (epicsThreadId id)
+static void startHook1 (epicsThreadId id)
{
- int no = findThreadIndex(id);
- order[no][5] = cnt[no]++;
+ int no = newThreadIndex(id);
+ order[no][0] = cnt[no]++;
+ epicsAtThreadExit(atExitHook1, NULL);
}
-static void exitHook2 (epicsThreadId id)
+static void startHook2 (epicsThreadId id)
{
int no = findThreadIndex(id);
- order[no][4] = cnt[no]++;
+ order[no][1] = cnt[no]++;
+ epicsAtThreadExit(atExitHook2, NULL);
}
static void my_thread (void *arg)
{
int no = findThreadIndex(epicsThreadGetIdSelf());
mine[no] = 1;
- epicsAtThreadExit(atExitHook1, NULL);
- epicsAtThreadExit(atExitHook2, NULL);
- epicsThreadSleep(0.1);
+ epicsEventMustWait((epicsEventId) arg);
+}
+
+static void mapper (epicsThreadId id)
+{
+ called[findThreadIndex(id)]++;
}
MAIN(epicsThreadHooksTest)
{
int i;
+ int ok;
- testPlan(THREAD_NO-1);
+ testPlan(THREAD_NO);
epicsThreadAddStartHook(startHook1);
- epicsThreadAddExitHook(exitHook1);
epicsThreadAddStartHook(startHook2);
- epicsThreadAddExitHook(exitHook2);
for (i = 0; i < THREAD_NO-1; i++) {
+ shutdown[i] = epicsEventCreate(epicsEventEmpty);
char name[10];
sprintf(name, "t%d", (int) i);
- epicsThreadCreate(name, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), my_thread, NULL);
+ epicsThreadCreate(name, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), my_thread, shutdown[i]);
+ }
+
+ epicsThreadMap(mapper);
+
+ ok = 1;
+ for (i = 0; i < THREAD_NO-1; i++) {
+ if (mine[i] && called[i] != 1) ok = 0;
+ }
+ testOk(ok, "All tasks covered once by epicsThreadMap");
+
+ for (i = 0; i < THREAD_NO-1; i++) {
+ epicsEventSignal(shutdown[i]);
}
epicsThreadSleep(1.0);
for (i = 0; i < THREAD_NO; i++) {
- int ok = 1;
int j;
for (j = 0; j < HOOKS_NO; j++) {
if (mine[i] && order[i][j]!=j) ok = 0;
}
- if (mine[i]) testOk(ok, "All %d hooks for task %d called in correct order", HOOKS_NO, (int)i);
+ if (mine[i]) testOk(ok, "All hooks for task %d called in correct order", (int)i);
}
return testDone();
}
From 137283ec0b70f175ac9c7b7ff37202974296e96f Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Tue, 3 Jul 2012 15:27:50 +0200
Subject: [PATCH 14/15] libCom/osi: Add default start hook for _main_ thread
---
src/libCom/osi/epicsThread.h | 2 +-
src/libCom/osi/os/Linux/osdThreadExtra.c | 2 ++
src/libCom/osi/os/RTEMS/osdThread.c | 2 +-
src/libCom/osi/os/WIN32/osdThread.c | 2 +-
src/libCom/osi/os/default/osdThreadExtra.c | 2 ++
src/libCom/osi/os/default/osdThreadHooks.c | 4 +++-
src/libCom/osi/os/posix/osdThread.c | 2 +-
src/libCom/osi/os/posix/osdThreadExtra.c | 6 ++++++
src/libCom/osi/os/vxWorks/osdThread.c | 2 +-
9 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h
index a94bd9c3b..23457a0af 100644
--- a/src/libCom/osi/epicsThread.h
+++ b/src/libCom/osi/epicsThread.h
@@ -103,7 +103,7 @@ epicsShareFunc void epicsShareAPI epicsThreadShow(
/* Hooks called when a thread starts, map function called once for every thread */
typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id);
-epicsShareFunc void epicsThreadHooksInit(void);
+epicsShareFunc void epicsThreadHooksInit(epicsThreadId id);
epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook);
epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func);
diff --git a/src/libCom/osi/os/Linux/osdThreadExtra.c b/src/libCom/osi/os/Linux/osdThreadExtra.c
index 61a0ef2bd..13a3b5df7 100644
--- a/src/libCom/osi/os/Linux/osdThreadExtra.c
+++ b/src/libCom/osi/os/Linux/osdThreadExtra.c
@@ -28,6 +28,7 @@
#include "epicsThread.h"
epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook;
void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
{
@@ -62,3 +63,4 @@ static void thread_hook(epicsThreadOSD *pthreadInfo)
}
EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook = thread_hook;
+EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook = thread_hook;
diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c
index 70a014539..f3871bc43 100644
--- a/src/libCom/osi/os/RTEMS/osdThread.c
+++ b/src/libCom/osi/os/RTEMS/osdThread.c
@@ -238,7 +238,7 @@ epicsThreadInit (void)
taskVarMutex = epicsMutexMustCreate ();
rtems_task_ident (RTEMS_SELF, 0, &tid);
setThreadInfo (tid, "_main_", NULL, NULL);
- epicsThreadHooksInit();
+ epicsThreadHooksInit(tid);
initialized = 1;
epicsThreadCreate ("ImsgDaemon", 99,
epicsThreadGetStackSize (epicsThreadStackSmall),
diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c
index e9c573731..30c72a10f 100644
--- a/src/libCom/osi/os/WIN32/osdThread.c
+++ b/src/libCom/osi/os/WIN32/osdThread.c
@@ -228,7 +228,7 @@ static win32ThreadGlobal * fetchWin32ThreadGlobal ( void )
pWin32ThreadGlobal = 0;
return 0;
}
- epicsThreadHooksInit ();
+ epicsThreadHooksInit (NULL);
InterlockedExchange ( & initCompleted, 1 );
diff --git a/src/libCom/osi/os/default/osdThreadExtra.c b/src/libCom/osi/os/default/osdThreadExtra.c
index 311db013d..a63ab910f 100644
--- a/src/libCom/osi/os/default/osdThreadExtra.c
+++ b/src/libCom/osi/os/default/osdThreadExtra.c
@@ -13,5 +13,7 @@
#include "shareLib.h"
epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook;
EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook;
diff --git a/src/libCom/osi/os/default/osdThreadHooks.c b/src/libCom/osi/os/default/osdThreadHooks.c
index 86f0113dd..3fb1e159d 100644
--- a/src/libCom/osi/os/default/osdThreadHooks.c
+++ b/src/libCom/osi/os/default/osdThreadHooks.c
@@ -21,6 +21,7 @@
epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id);
epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook;
#define checkStatusOnceReturn(status, message, method) \
if((status)) { \
@@ -50,12 +51,13 @@ epicsShareFunc void epicsThreadAddStartHook(EPICS_THREAD_HOOK_ROUTINE hook)
epicsMutexUnlock(hookLock);
}
-epicsShareFunc void epicsThreadHooksInit(void)
+epicsShareFunc void epicsThreadHooksInit(epicsThreadId id)
{
if (!hookLock) {
hookLock = epicsMutexMustCreate();
if (epicsThreadDefaultStartHook) epicsThreadAddStartHook(epicsThreadDefaultStartHook);
}
+ if (id && epicsThreadMainStartHook) epicsThreadMainStartHook(id);
}
epicsShareFunc void epicsThreadRunStartHooks(epicsThreadId id)
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index 6eac4f8b8..f0926d230 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -354,7 +354,7 @@ static void once(void)
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadInit");
status = atexit(epicsExitCallAtExits);
checkStatusOnce(status,"atexit");
- epicsThreadHooksInit();
+ epicsThreadHooksInit(pthreadInfo);
epicsThreadOnceCalled = 1;
}
diff --git a/src/libCom/osi/os/posix/osdThreadExtra.c b/src/libCom/osi/os/posix/osdThreadExtra.c
index 9df3485af..8d4338e31 100644
--- a/src/libCom/osi/os/posix/osdThreadExtra.c
+++ b/src/libCom/osi/os/posix/osdThreadExtra.c
@@ -17,6 +17,12 @@
#include "epicsEvent.h"
#include "epicsThread.h"
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+epicsShareExtern EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook;
+
+EPICS_THREAD_HOOK_ROUTINE epicsThreadDefaultStartHook;
+EPICS_THREAD_HOOK_ROUTINE epicsThreadMainStartHook;
+
void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
{
if(!pthreadInfo) {
diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c
index 7953c03ef..9a9eea5d2 100644
--- a/src/libCom/osi/os/vxWorks/osdThread.c
+++ b/src/libCom/osi/os/vxWorks/osdThread.c
@@ -105,7 +105,7 @@ static void epicsThreadInit(void)
static int lock = 0;
while(!vxTas(&lock)) taskDelay(1);
- epicsThreadHooksInit();
+ epicsThreadHooksInit(NULL);
mutexInit(epicsThreadOnceMutex);
mutexInit(epicsThreadListMutex);
taskIdList = calloc(ID_LIST_CHUNK, sizeof(int));
From 39ed8f3d024808c5782e60fed94308d1aef6c4ce Mon Sep 17 00:00:00 2001
From: Ralph Lange
Date: Tue, 3 Jul 2012 16:39:57 +0200
Subject: [PATCH 15/15] documentation: Updated RELEASE_NOTES
---
documentation/RELEASE_NOTES.html | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 9b78e72e0..8c8705af0 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -15,12 +15,12 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.
Changes between 3.14.x and 3.15.0.x
-New API to hook into thread creation and deletion
+New API to hook into thread creation
A hook API has been added allowing user-supplied functions to be called
-whenever a thread starts or exits. The calls are made from the thread's
-context, and can be used to control additional thread properties not handled
-inside EPICS base, e.g. setting the scheduling policy or CPU affinity (on SMP
+whenever a thread starts. The calls are made from the thread's context,
+and can be used to control additional thread properties not handled inside
+EPICS base, e.g. setting the scheduling policy or CPU affinity (on SMP
systems).
The API also supports a mapping operation, calling a user-supplied function