added threadInit, threadExitMain and modified threadShow family
This commit is contained in:
@@ -34,7 +34,6 @@ typedef struct commonAttr{
|
||||
int schedPolicy;
|
||||
} commonAttr;
|
||||
|
||||
|
||||
typedef struct threadInfo {
|
||||
ELLNODE node;
|
||||
pthread_t tid;
|
||||
@@ -48,7 +47,6 @@ typedef struct threadInfo {
|
||||
char *name;
|
||||
} threadInfo;
|
||||
|
||||
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
static pthread_key_t getpthreadInfo;
|
||||
static semMutexId onceMutex;
|
||||
static semMutexId listMutex;
|
||||
@@ -125,7 +123,21 @@ static threadInfo * init_threadInfo(const char *name,
|
||||
pthreadInfo->suspendSem = semBinaryMustCreate(semFull);
|
||||
pthreadInfo->name = mallocMustSucceed(strlen(name)+1,"threadCreate");
|
||||
strcpy(pthreadInfo->name,name);
|
||||
return((threadId)pthreadInfo);
|
||||
return(pthreadInfo);
|
||||
}
|
||||
|
||||
static void free_threadInfo(threadInfo *pthreadInfo)
|
||||
{
|
||||
int status;
|
||||
|
||||
semMutexMustTake(listMutex);
|
||||
ellDelete(&pthreadList,(ELLNODE *)pthreadInfo);
|
||||
semMutexGive(listMutex);
|
||||
semBinaryDestroy(pthreadInfo->suspendSem);
|
||||
status = pthread_attr_destroy(&pthreadInfo->attr);
|
||||
checkStatusQuit(status,"pthread_attr_destroy","free_threadInfo");
|
||||
free(pthreadInfo->name);
|
||||
free(pthreadInfo);
|
||||
}
|
||||
|
||||
static void once(void)
|
||||
@@ -137,9 +149,9 @@ static void once(void)
|
||||
onceMutex = semMutexMustCreate();
|
||||
listMutex = semMutexMustCreate();
|
||||
ellInit(&pthreadList);
|
||||
pcommonAttr = callocMustSucceed(1,sizeof(commonAttr),"osdThread::once");
|
||||
pcommonAttr = callocMustSucceed(1,sizeof(commonAttr),"threadInit");
|
||||
status = pthread_attr_init(&pcommonAttr->attr);
|
||||
checkStatusQuit(status,"pthread_attr_init","osdThread::once");
|
||||
checkStatusQuit(status,"pthread_attr_init","threadInit");
|
||||
status = pthread_attr_setdetachstate(
|
||||
&pcommonAttr->attr, PTHREAD_CREATE_DETACHED);
|
||||
checkStatus(status,"pthread_attr_setdetachstate");
|
||||
@@ -175,44 +187,20 @@ static void once(void)
|
||||
semMutexGive(listMutex);
|
||||
}
|
||||
|
||||
void threadOnceOsd(threadOnceId *id, void (*func)(void *), void *arg)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadOnce");
|
||||
|
||||
semMutexMustTake(onceMutex);
|
||||
if (*id == 0) { /* 0 => first call */
|
||||
*id = -1; /* -1 => func() active */
|
||||
func(arg);
|
||||
*id = +1; /* +1 => func() done (see threadOnce() macro defn) */
|
||||
}
|
||||
semMutexGive(onceMutex);
|
||||
}
|
||||
|
||||
static void * start_routine(void *arg)
|
||||
{
|
||||
threadInfo *pthreadInfo = (threadInfo *)arg;
|
||||
int status;
|
||||
|
||||
status = pthread_setspecific(getpthreadInfo,arg);
|
||||
checkStatusQuit(status,"pthread_setspecific","start_routine");
|
||||
|
||||
semMutexMustTake(listMutex);
|
||||
ellAdd(&pthreadList,(ELLNODE *)pthreadInfo);
|
||||
semMutexGive(listMutex);
|
||||
|
||||
(*pthreadInfo->createFunc)(pthreadInfo->createArg);
|
||||
|
||||
semMutexMustTake(listMutex);
|
||||
ellDelete(&pthreadList,(ELLNODE *)pthreadInfo);
|
||||
semMutexGive(listMutex);
|
||||
|
||||
semBinaryDestroy(pthreadInfo->suspendSem);
|
||||
status = pthread_attr_destroy(&pthreadInfo->attr);
|
||||
checkStatusQuit(status,"pthread_attr_destroy","start_routine");
|
||||
free(pthreadInfo->name);
|
||||
free(pthreadInfo);
|
||||
free_threadInfo(pthreadInfo);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -245,37 +233,50 @@ unsigned int threadGetStackSize (threadStackSizeClass stackSizeClass)
|
||||
#endif /* OSITHREAD_USE_DEFAULT_STACK */
|
||||
}
|
||||
|
||||
/* the following technique is mt-safe for initializing osiThread because
|
||||
only the main thread calls threadInit(); other libraries should use
|
||||
threadOnce() for one-time initialization */
|
||||
void threadInit(void)
|
||||
{
|
||||
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
static int initialized = 0;
|
||||
|
||||
if (!initialized) {
|
||||
/* don't actually have to use pthread_once() for this; could call
|
||||
once() directly or include its body here */
|
||||
int status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadInit");
|
||||
initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* threadOnce is a macro that calls threadOnceOsd */
|
||||
void threadOnceOsd(threadOnceId *id, void (*func)(void *), void *arg)
|
||||
{
|
||||
semMutexMustTake(onceMutex);
|
||||
if (*id == 0) { /* 0 => first call */
|
||||
*id = -1; /* -1 => func() active */
|
||||
func(arg);
|
||||
*id = +1; /* +1 => func() done (see threadOnce() macro defn) */
|
||||
}
|
||||
semMutexGive(onceMutex);
|
||||
}
|
||||
|
||||
threadId threadCreate(const char *name,
|
||||
unsigned int priority, unsigned int stackSize,
|
||||
THREADFUNC funptr,void *parm)
|
||||
{
|
||||
threadInfo *pthreadInfo;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadCreate");
|
||||
pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm);
|
||||
status = pthread_create(&pthreadInfo->tid,
|
||||
&pthreadInfo->attr,start_routine,pthreadInfo);
|
||||
threadInfo *pthreadInfo = init_threadInfo(name,priority,stackSize,
|
||||
funptr,parm);
|
||||
int status = pthread_create(&pthreadInfo->tid,
|
||||
&pthreadInfo->attr,start_routine,pthreadInfo);
|
||||
checkStatusQuit(status,"pthread_create","threadCreate");
|
||||
return((threadId)pthreadInfo);
|
||||
}
|
||||
|
||||
void threadSuspendSelf()
|
||||
void threadSuspendSelf(void)
|
||||
{
|
||||
threadInfo *pthreadInfo;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadSuspendSelf");
|
||||
pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
if(!pthreadInfo) {
|
||||
errlogPrintf("threadSuspendSelf pthread_getspecific returned 0\n");
|
||||
while(1) {
|
||||
errlogPrintf("sleeping for 5 seconds\n");
|
||||
threadSleep(5.0);
|
||||
}
|
||||
}
|
||||
threadInfo *pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
pthreadInfo->isSuspended = 1;
|
||||
semBinaryMustTake(pthreadInfo->suspendSem);
|
||||
}
|
||||
@@ -287,6 +288,18 @@ void threadResume(threadId id)
|
||||
semBinaryGive(pthreadInfo->suspendSem);
|
||||
}
|
||||
|
||||
void threadExitMain(void)
|
||||
{
|
||||
threadInfo *pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
if(pthreadInfo->createFunc) {
|
||||
errlogPrintf("called from non-main thread\n");
|
||||
cantProceed("threadExitMain");
|
||||
}
|
||||
else {
|
||||
free_threadInfo(pthreadInfo);
|
||||
pthread_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int threadGetPriority(threadId id)
|
||||
{
|
||||
@@ -294,7 +307,6 @@ unsigned int threadGetPriority(threadId id)
|
||||
return(pthreadInfo->osiPriority);
|
||||
}
|
||||
|
||||
|
||||
void threadSetPriority(threadId id,unsigned int priority)
|
||||
{
|
||||
threadInfo *pthreadInfo = (threadInfo *)id;
|
||||
@@ -337,22 +349,12 @@ void threadSleep(double seconds)
|
||||
}
|
||||
|
||||
threadId threadGetIdSelf(void) {
|
||||
threadInfo *pthreadInfo;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadGetIdSelf");
|
||||
pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
threadInfo *pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
return((threadId)pthreadInfo);
|
||||
}
|
||||
|
||||
threadId threadGetId(const char *name) {
|
||||
threadInfo *pthreadInfo;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadGetId");
|
||||
|
||||
semMutexMustTake(listMutex);
|
||||
for(pthreadInfo=(threadInfo *)ellFirst(&pthreadList); pthreadInfo;
|
||||
pthreadInfo=(threadInfo *)ellNext((ELLNODE *)pthreadInfo)) {
|
||||
@@ -364,43 +366,43 @@ threadId threadGetId(const char *name) {
|
||||
|
||||
const char *threadGetNameSelf()
|
||||
{
|
||||
threadInfo *pthreadInfo;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadGetNameSelf");
|
||||
pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
threadInfo *pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo);
|
||||
return(pthreadInfo->name);
|
||||
}
|
||||
|
||||
void threadGetName(threadId id, char *name, size_t size)
|
||||
{
|
||||
threadInfo *pthreadInfo = (threadInfo *)id;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadGetName");
|
||||
strncpy (name, pthreadInfo->name, size - 1);
|
||||
strncpy(name, pthreadInfo->name, size-1);
|
||||
name[size-1] = '\0';
|
||||
}
|
||||
|
||||
void threadShow (void)
|
||||
void threadShowAll(unsigned int level)
|
||||
{
|
||||
threadInfo *pthreadInfo;
|
||||
int status;
|
||||
|
||||
status = pthread_once(&once_control,once);
|
||||
checkStatusQuit(status,"pthread_once","threadShow");
|
||||
|
||||
errlogPrintf (" NAME ID PRI STATE WAIT\n");
|
||||
threadShow(0,level);
|
||||
semMutexMustTake(listMutex);
|
||||
for(pthreadInfo=(threadInfo *)ellFirst(&pthreadList); pthreadInfo;
|
||||
pthreadInfo=(threadInfo *)ellNext((ELLNODE *)pthreadInfo)) {
|
||||
errlogPrintf("%12.12s %8x %8d\n", pthreadInfo->name,(threadId)
|
||||
pthreadInfo,pthreadInfo->osiPriority);
|
||||
}
|
||||
pthreadInfo=(threadInfo *)ellNext((ELLNODE *)pthreadInfo))
|
||||
threadShow((threadId)pthreadInfo,level);
|
||||
semMutexGive(listMutex);
|
||||
}
|
||||
|
||||
void threadShow(threadId id,unsigned int level)
|
||||
{
|
||||
threadInfo *pthreadInfo = (threadInfo *)id;
|
||||
|
||||
if(!id) {
|
||||
errlogPrintf (" NAME ID PRI STATE WAIT\n");
|
||||
}
|
||||
else {
|
||||
errlogPrintf("%12.12s %8x %8d\n", pthreadInfo->name,(threadId)
|
||||
pthreadInfo,pthreadInfo->osiPriority);
|
||||
if(level>0)
|
||||
; /* more info */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
threadPrivateId threadPrivateCreate(void)
|
||||
{
|
||||
|
||||
@@ -15,12 +15,12 @@ typedef void (*THREADFUNC)(void *parm);
|
||||
static const unsigned threadPriorityMax = 99;
|
||||
static const unsigned threadPriorityMin = 0;
|
||||
|
||||
/*some generic values */
|
||||
/* some generic values */
|
||||
static const unsigned threadPriorityLow = 10;
|
||||
static const unsigned threadPriorityMedium = 50;
|
||||
static const unsigned threadPriorityHigh = 90;
|
||||
|
||||
/*some iocCore specific values */
|
||||
/* some iocCore specific values */
|
||||
static const unsigned threadPriorityChannelAccessClient = 10;
|
||||
static const unsigned threadPriorityChannelAccessServer = 20;
|
||||
static const unsigned threadPriorityScanLow = 60;
|
||||
@@ -38,19 +38,22 @@ typedef int threadOnceId;
|
||||
|
||||
/* void threadOnce(threadOnceId *id, void (*func)(void *), void *arg); */
|
||||
/* threadOnce is implemented as a macro */
|
||||
/*threadOnceOsd should not be called by user code*/
|
||||
/* threadOnceOsd should not be called by user code */
|
||||
epicsShareFunc void epicsShareAPI threadOnceOsd(
|
||||
threadOnceId *id, void (*func)(void *), void *arg);
|
||||
|
||||
#define threadOnce(id,func,arg) \
|
||||
if(*(id)==0) threadOnceOsd((id),(func),(arg))
|
||||
if(*(id)<=0) threadOnceOsd((id),(func),(arg))
|
||||
|
||||
/* (threadId)0 is guaranteed to be an invalid thread id */
|
||||
typedef void *threadId;
|
||||
epicsShareFunc void epicsShareAPI threadInit(void);
|
||||
epicsShareFunc threadId epicsShareAPI threadCreate(const char *name,
|
||||
unsigned int priority, unsigned int stackSize,
|
||||
THREADFUNC funptr,void *parm);
|
||||
epicsShareFunc void epicsShareAPI threadSuspendSelf(void);
|
||||
epicsShareFunc void epicsShareAPI threadResume(threadId id);
|
||||
epicsShareFunc void epicsShareAPI threadExitMain(void);
|
||||
epicsShareFunc unsigned int epicsShareAPI threadGetPriority(threadId id);
|
||||
epicsShareFunc void epicsShareAPI threadSetPriority(
|
||||
threadId id,unsigned int priority);
|
||||
@@ -67,7 +70,8 @@ epicsShareFunc const char * epicsShareAPI threadGetNameSelf(void);
|
||||
/* Failure results in an empty string stored in name */
|
||||
epicsShareFunc void epicsShareAPI threadGetName(threadId id, char *name, size_t size);
|
||||
|
||||
epicsShareFunc void epicsShareAPI threadShow(void);
|
||||
epicsShareFunc void epicsShareAPI threadShowAll(unsigned int level);
|
||||
epicsShareFunc void epicsShareAPI threadShow(threadId id,unsigned int level);
|
||||
|
||||
typedef void * threadPrivateId;
|
||||
epicsShareFunc threadPrivateId epicsShareAPI threadPrivateCreate (void);
|
||||
|
||||
Reference in New Issue
Block a user