From fbf62189cbabdc96b9e431ed60b0557e0c6079ea Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 2 Jul 2019 17:27:27 -0500 Subject: [PATCH] Replace epicsThreadOptsDefaults() with EPICS_THREAD_OPTS_INIT The epicsThreadCreate() routines now interpose calls to epicsThreadGetStackSize() if an enum value is passed. --- modules/database/src/ioc/as/asCa.c | 4 +- modules/database/src/ioc/db/dbCa.c | 4 +- modules/database/src/ioc/db/dbEvent.c | 3 +- modules/libcom/src/osi/epicsThread.cpp | 9 ++- modules/libcom/src/osi/epicsThread.h | 15 +++-- modules/libcom/src/osi/os/RTEMS/osdThread.c | 20 +++--- modules/libcom/src/osi/os/WIN32/osdThread.c | 18 ++--- modules/libcom/src/osi/os/posix/osdThread.c | 66 +++++++++++-------- modules/libcom/src/osi/os/vxWorks/osdThread.c | 26 ++++---- modules/libcom/test/epicsThreadTest.cpp | 16 ++--- 10 files changed, 95 insertions(+), 86 deletions(-) diff --git a/modules/database/src/ioc/as/asCa.c b/modules/database/src/ioc/as/asCa.c index e8c5403d9..21bb47f5f 100644 --- a/modules/database/src/ioc/as/asCa.c +++ b/modules/database/src/ioc/as/asCa.c @@ -229,8 +229,8 @@ static void asCaTask(void) void asCaStart(void) { - epicsThreadOpts opts; - epicsThreadOptsDefaults(&opts); + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; + opts.stackSize = epicsThreadGetStackSize(epicsThreadStackBig); opts.priority = epicsThreadPriorityScanLow - 3; opts.joinable = 1; diff --git a/modules/database/src/ioc/db/dbCa.c b/modules/database/src/ioc/db/dbCa.c index 935c397d4..ea0fad0d3 100644 --- a/modules/database/src/ioc/db/dbCa.c +++ b/modules/database/src/ioc/db/dbCa.c @@ -265,8 +265,8 @@ void dbCaShutdown(void) static void dbCaLinkInitImpl(int isolate) { - epicsThreadOpts opts; - epicsThreadOptsDefaults(&opts); + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; + opts.stackSize = epicsThreadGetStackSize(epicsThreadStackBig); opts.priority = epicsThreadPriorityMedium; opts.joinable = 1; diff --git a/modules/database/src/ioc/db/dbEvent.c b/modules/database/src/ioc/db/dbEvent.c index 48dc9012b..febe62634 100644 --- a/modules/database/src/ioc/db/dbEvent.c +++ b/modules/database/src/ioc/db/dbEvent.c @@ -1056,9 +1056,8 @@ int db_start_events ( void *init_func_arg, unsigned osiPriority ) { struct event_user * const evUser = (struct event_user *) ctx; - epicsThreadOpts opts; + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; - epicsThreadOptsDefaults(&opts); opts.stackSize = epicsThreadGetStackSize(epicsThreadStackMedium); opts.priority = osiPriority; opts.joinable = 1; diff --git a/modules/libcom/src/osi/epicsThread.cpp b/modules/libcom/src/osi/epicsThread.cpp index 9a049133f..92f833847 100644 --- a/modules/libcom/src/osi/epicsThread.cpp +++ b/modules/libcom/src/osi/epicsThread.cpp @@ -35,7 +35,7 @@ epicsThreadId epicsShareAPI epicsThreadCreate ( const char * name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr,void * parm ) { - epicsThreadOpts opts; + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; opts.priority = priority; opts.stackSize = stackSize; opts.joinable = 0; @@ -202,11 +202,10 @@ epicsThread::epicsThread ( epicsThreadRunable & runableIn, const char * pName, unsigned stackSize, unsigned priority ) : runable ( runableIn ), id ( 0 ), pThreadDestroyed ( 0 ), - begin ( false ), cancel ( false ), terminated ( false ) - , joined(false) + begin ( false ), cancel ( false ), terminated ( false ), + joined ( false ) { - epicsThreadOpts opts; - epicsThreadOptsDefaults(&opts); + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; opts.stackSize = stackSize; opts.priority = priority; opts.joinable = 1; diff --git a/modules/libcom/src/osi/epicsThread.h b/modules/libcom/src/osi/epicsThread.h index 694ac94c7..82fa04b5b 100644 --- a/modules/libcom/src/osi/epicsThread.h +++ b/modules/libcom/src/osi/epicsThread.h @@ -84,9 +84,8 @@ epicsShareFunc void epicsShareAPI epicsThreadExitMain(void); typedef struct epicsThreadOpts { /** Thread priority in OSI range (cf. epicsThreadPriority*) */ unsigned int priority; - /** Thread stack size, as returned by epicsThreadGetStackSize(). - * - * @warning Do not pass enum epicsThreadStackSizeClass directly! + /** Thread stack size, either in bytes for this architecture or + * an enum epicsThreadStackSizeClass value. */ unsigned int stackSize; /** Should thread be joinable? (default (0) is not joinable). @@ -95,8 +94,14 @@ typedef struct epicsThreadOpts { unsigned int joinable; } epicsThreadOpts; -/** Fill in target specific default values. */ -epicsShareFunc void epicsThreadOptsDefaults(epicsThreadOpts *opts); +/** Default initial values for epicsThreadOpts + * Applications should always use this macro to initialize an epicsThreadOpts + * structure. Additional fields may be added in the future, and the order of + * the fields might also change, thus code that assumes the above definition + * might break if these rules are not followed. + */ +#define EPICS_THREAD_OPTS_INIT { \ + epicsThreadPriorityLow, epicsThreadStackMedium, 0} /** @brief Allocate and start a new OS thread. * @param name A name describing this thread. Appears in various log and error message. diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.c b/modules/libcom/src/osi/os/RTEMS/osdThread.c index fdc31759f..bdcd8c17e 100644 --- a/modules/libcom/src/osi/os/RTEMS/osdThread.c +++ b/modules/libcom/src/osi/os/RTEMS/osdThread.c @@ -152,13 +152,6 @@ epicsThreadGetStackSize (epicsThreadStackSizeClass size) return stackSize; } -static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, 5000, 0}; - -void epicsThreadOptsDefaults(epicsThreadOpts *opts) -{ - *opts = opts_default; -} - /* * Ensure integrity of task variable list */ @@ -315,15 +308,22 @@ epicsThreadCreateOpt ( const char * name, EPICSTHREADFUNC funptr, void * parm, const epicsThreadOpts *opts ) { + unsigned int stackSize; rtems_id tid; rtems_status_code sc; char c[4]; - unsigned stackSize; - if(!opts) opts = &opts_default; + if (!initialized) + epicsThreadInit(); + + if (!opts) { + static const epicsThreadOpts opts_default = EPICS_THREAD_OPTS_INIT; + opts = &opts_default; + } stackSize = opts->stackSize; + if (stackSize <= epicsThreadStackBig) + stackSize = epicsThreadGetStackSize(stackSize); - if (!initialized) epicsThreadInit(); if (stackSize < RTEMS_MINIMUM_STACK_SIZE) { errlogPrintf ("Warning: epicsThreadCreate %s illegal stackSize %d\n", name, stackSize); diff --git a/modules/libcom/src/osi/os/WIN32/osdThread.c b/modules/libcom/src/osi/os/WIN32/osdThread.c index 6d43e769f..1cfa1ec5c 100644 --- a/modules/libcom/src/osi/os/WIN32/osdThread.c +++ b/modules/libcom/src/osi/os/WIN32/osdThread.c @@ -469,13 +469,6 @@ epicsShareFunc unsigned int epicsShareAPI return stackSizeTable[stackSizeClass]; } -static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, STACK_SIZE(1), 0}; - -void epicsThreadOptsDefaults(epicsThreadOpts *opts) -{ - *opts = opts_default; -} - void epicsThreadCleanupWIN32 () { win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); @@ -599,6 +592,7 @@ epicsThreadId epicsThreadCreateOpt ( { win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); win32ThreadParam * pParmWIN32; + unsigned int stackSize; int osdPriority; DWORD wstat; BOOL bstat; @@ -607,7 +601,13 @@ epicsThreadId epicsThreadCreateOpt ( return NULL; } - if(!opts) opts = &opts_default; + if (!opts) { + static const epicsThreadOpts opts_default = EPICS_THREAD_OPTS_INIT; + opts = &opts_default; + } + stackSize = opts->stackSize; + if (stackSize <= epicsThreadStackBig) + stackSize = epicsThreadGetStackSize(stackSize); pParmWIN32 = epicsThreadParmCreate ( pName ); if ( pParmWIN32 == 0 ) { @@ -620,7 +620,7 @@ epicsThreadId epicsThreadCreateOpt ( { unsigned threadId; pParmWIN32->handle = (HANDLE) _beginthreadex ( - 0, opts->stackSize, epicsWin32ThreadEntry, + 0, stackSize, epicsWin32ThreadEntry, pParmWIN32, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, & threadId ); diff --git a/modules/libcom/src/osi/os/posix/osdThread.c b/modules/libcom/src/osi/os/posix/osdThread.c index 5ed2cbc56..ea0d2b265 100644 --- a/modules/libcom/src/osi/os/posix/osdThread.c +++ b/modules/libcom/src/osi/os/posix/osdThread.c @@ -469,13 +469,6 @@ epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadSt return 0; #endif /*_POSIX_THREAD_ATTR_STACKSIZE*/ } - -static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, STACK_SIZE(1), 0}; - -void epicsThreadOptsDefaults(epicsThreadOpts *opts) -{ - *opts = opts_default; -} epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg) { @@ -519,48 +512,65 @@ epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (* } epicsThreadId -epicsThreadCreateOpt ( - const char * name, +epicsThreadCreateOpt(const char * name, EPICSTHREADFUNC funptr, void * parm, const epicsThreadOpts *opts ) { + unsigned int stackSize; epicsThreadOSD *pthreadInfo; int status; sigset_t blockAllSig, oldSig; - if(!opts) opts = &opts_default; - epicsThreadInit(); assert(pcommonAttr); + + if (!opts) { + static const epicsThreadOpts opts_default = EPICS_THREAD_OPTS_INIT; + opts = &opts_default; + } + stackSize = opts->stackSize; + if (stackSize <= epicsThreadStackBig) + stackSize = epicsThreadGetStackSize(stackSize); + sigfillset(&blockAllSig); - pthread_sigmask(SIG_SETMASK,&blockAllSig,&oldSig); - pthreadInfo = init_threadInfo(name,opts->priority,opts->stackSize,funptr,parm,opts->joinable); - if(pthreadInfo==0) return 0; + pthread_sigmask(SIG_SETMASK, &blockAllSig, &oldSig); + + pthreadInfo = init_threadInfo(name, opts->priority, stackSize, funptr, + parm, opts->joinable); + if (pthreadInfo==0) + return 0; + pthreadInfo->isEpicsThread = 1; - setSchedulingPolicy(pthreadInfo,SCHED_FIFO); + setSchedulingPolicy(pthreadInfo, SCHED_FIFO); pthreadInfo->isRealTimeScheduled = 1; - status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr, - start_routine,pthreadInfo); - if(status==EPERM){ + + status = pthread_create(&pthreadInfo->tid, &pthreadInfo->attr, + start_routine, pthreadInfo); + if (status==EPERM) { /* Try again without SCHED_FIFO*/ free_threadInfo(pthreadInfo); - pthreadInfo = init_threadInfo(name,opts->priority,opts->stackSize,funptr,parm,opts->joinable); - if(pthreadInfo==0) return 0; + + pthreadInfo = init_threadInfo(name, opts->priority, stackSize, + funptr, parm, opts->joinable); + if (pthreadInfo==0) + return 0; + pthreadInfo->isEpicsThread = 1; - status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr, - start_routine,pthreadInfo); + status = pthread_create(&pthreadInfo->tid, &pthreadInfo->attr, + start_routine, pthreadInfo); } - checkStatusOnce(status,"pthread_create"); - if(status) { + checkStatusOnce(status, "pthread_create"); + if (status) { free_threadInfo(pthreadInfo); return 0; } - status = pthread_sigmask(SIG_SETMASK,&oldSig,NULL); - checkStatusOnce(status,"pthread_sigmask"); - if(pthreadInfo->joinable) { + + status = pthread_sigmask(SIG_SETMASK, &oldSig, NULL); + checkStatusOnce(status, "pthread_sigmask"); + if (pthreadInfo->joinable) { /* extra ref for epicsThreadMustJoin() */ epicsAtomicIncrIntT(&pthreadInfo->refcnt); } - return(pthreadInfo); + return pthreadInfo; } /* diff --git a/modules/libcom/src/osi/os/vxWorks/osdThread.c b/modules/libcom/src/osi/os/vxWorks/osdThread.c index 43770eab3..d5b859ade 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdThread.c +++ b/modules/libcom/src/osi/os/vxWorks/osdThread.c @@ -150,13 +150,6 @@ unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass) return stackSizeTable[stackSizeClass]; } -static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, 4000*ARCH_STACK_FACTOR, 0}; - -void epicsThreadOptsDefaults(epicsThreadOpts *opts) -{ - *opts = opts_default; -} - struct epicsThreadOSD {}; /* Strictly speaking this should be a WIND_TCB, but we only need it to * be able to create an epicsThreadId that is guaranteed never to be @@ -256,20 +249,27 @@ static void createFunction(EPICSTHREADFUNC func, void *parm) epicsThreadId epicsThreadCreateOpt(const char * name, EPICSTHREADFUNC funptr, void * parm, const epicsThreadOpts *opts ) { + unsigned int stackSize; int tid; - if (!opts) - opts = &opts_default; - epicsThreadInit(); - if (opts->stackSize < 100) { + + if (!opts) { + static const epicsThreadOpts opts_default = EPICS_THREAD_OPTS_INIT; + opts = &opts_default; + } + stackSize = opts->stackSize; + if (stackSize <= epicsThreadStackBig) + stackSize = epicsThreadGetStackSize(stackSize); + + if (stackSize < 100) { errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n", - name, opts->stackSize); + name, stackSize); return 0; } tid = taskCreate((char *)name,getOssPriorityValue(opts->priority), - TASK_FLAGS, opts->stackSize, + TASK_FLAGS, stackSize, (FUNCPTR)createFunction, (int)funptr, (int)parm, 0,0,0,0,0,0,0,0); if (tid == ERROR) { diff --git a/modules/libcom/test/epicsThreadTest.cpp b/modules/libcom/test/epicsThreadTest.cpp index 6785f32ba..d07552d15 100644 --- a/modules/libcom/test/epicsThreadTest.cpp +++ b/modules/libcom/test/epicsThreadTest.cpp @@ -40,7 +40,7 @@ private: }; myThread::myThread(int arg,const char *name) : - thread(*this,name,epicsThreadGetStackSize(epicsThreadStackSmall),50+arg), + thread(*this,name,epicsThreadStackSmall,50+arg), argvalue(0) { argvalue = new int; @@ -132,16 +132,14 @@ void joinTests(void *arg) void testJoining() { - epicsThreadOpts opts; - epicsThreadOptsDefaults(&opts); - opts.priority = 50; - opts.joinable = 1; - + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; epicsEvent finished, trigger; - struct joinStuff stuff = { &opts, &trigger, &finished }; + + opts.priority = 50; + opts.joinable = 1; epicsThreadCreateOpt("parent", &joinTests, &stuff, &opts); // as selfjoin joins itself, we can't. @@ -172,9 +170,8 @@ static void thread(void *arg) static void testOkToBlock() { + epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; - epicsThreadOpts opts; - epicsThreadOptsDefaults(&opts); opts.priority = 50; opts.joinable = 1; @@ -190,7 +187,6 @@ static void testOkToBlock() epicsThreadMustJoin(threadA); testOk1(infoA.didSomething); - }