From 1125a4fe09db50be7e140665ade5dc07198f78cc Mon Sep 17 00:00:00 2001 From: William Lupton Date: Sat, 4 Mar 2000 02:59:50 +0000 Subject: [PATCH] added threadInit, threadExitMain and modified threadShow family --- src/libCom/osi/os/posix/osdThread.c | 176 ++++++++++++++-------------- src/libCom/osi/osiThread.h | 14 ++- 2 files changed, 98 insertions(+), 92 deletions(-) diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c index cd2c3fc7c..7c8ebf4df 100644 --- a/src/libCom/osi/os/posix/osdThread.c +++ b/src/libCom/osi/os/posix/osdThread.c @@ -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) { diff --git a/src/libCom/osi/osiThread.h b/src/libCom/osi/osiThread.h index c2830977e..92df2df07 100644 --- a/src/libCom/osi/osiThread.h +++ b/src/libCom/osi/osiThread.h @@ -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);