libCom: add epicsThreadCreateOpt()

Variant of epicsThreadCreate() which accepts optional
arguments via a structure to allow for compatible
addition of new arguments.
This commit is contained in:
Michael Davidsaver
2018-04-04 11:01:45 -07:00
parent 30268e3577
commit ca800fa57d
6 changed files with 100 additions and 24 deletions

View File

@@ -31,6 +31,17 @@
using namespace std;
epicsThreadId epicsShareAPI epicsThreadCreate (
const char * name, unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void * parm )
{
epicsThreadOpts opts;
opts.priority = priority;
opts.stackSize = stackSize;
return epicsThreadCreateOpt(name, funptr, parm, &opts);
}
epicsThreadRunable::~epicsThreadRunable () {}
void epicsThreadRunable::run () {}
void epicsThreadRunable::show ( unsigned int ) const {}

View File

@@ -65,6 +65,22 @@ epicsShareFunc void epicsThreadRealtimeLock(void);
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!
*/
unsigned int stackSize;
} epicsThreadOpts;
epicsShareFunc void epicsThreadOptsDefaults(epicsThreadOpts *opts);
epicsShareFunc epicsThreadId epicsThreadCreateOpt (
const char * name,
EPICSTHREADFUNC funptr, void * parm,
const epicsThreadOpts *opts );
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (
const char * name, unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void * parm );

View File

@@ -148,6 +148,13 @@ epicsThreadGetStackSize (epicsThreadStackSizeClass size)
return stackSize;
}
static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, 5000};
void epicsThreadOptsDefaults(epicsThreadOpts *opts)
{
*opts = opts_default;
}
/*
* Ensure integrity of task variable list
*/
@@ -263,13 +270,17 @@ void epicsThreadRealtimeLock(void)
* Create and start a new thread
*/
epicsThreadId
epicsThreadCreate (const char *name,
unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm)
epicsThreadCreateOpt (
const char * name,
EPICSTHREADFUNC funptr, void * parm, const epicsThreadOpts *opts )
{
rtems_id tid;
rtems_status_code sc;
char c[4];
unsigned stackSize;
if(!opts) opts = &opts_default;
stackSize = opts->stackSize;
if (!initialized) epicsThreadInit();
if (stackSize < RTEMS_MINIMUM_STACK_SIZE) {
@@ -279,7 +290,7 @@ epicsThreadCreate (const char *name,
}
strncpy (c, name, sizeof c);
sc = rtems_task_create (rtems_build_name (c[0], c[1], c[2], c[3]),
epicsThreadGetOssPriorityValue (priority),
epicsThreadGetOssPriorityValue (opts->priority),
stackSize,
RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
RTEMS_FLOATING_POINT|RTEMS_LOCAL,

View File

@@ -464,6 +464,13 @@ epicsShareFunc unsigned int epicsShareAPI
return stackSizeTable[stackSizeClass];
}
static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, STACK_SIZE(1)};
void epicsThreadOptsDefaults(epicsThreadOpts *opts)
{
*opts = opts_default;
}
void epicsThreadCleanupWIN32 ()
{
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
@@ -579,8 +586,10 @@ static win32ThreadParam * epicsThreadImplicitCreate ( void )
/*
* epicsThreadCreate ()
*/
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC pFunc,void *pParm)
epicsThreadId epicsThreadCreateOpt (
const char * pName,
EPICSTHREADFUNC pFunc, void * pParm,
const epicsThreadOpts *opts )
{
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
win32ThreadParam * pParmWIN32;
@@ -592,18 +601,20 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
return NULL;
}
if(!opts) opts = &opts_default;
pParmWIN32 = epicsThreadParmCreate ( pName );
if ( pParmWIN32 == 0 ) {
return ( epicsThreadId ) pParmWIN32;
}
pParmWIN32->funptr = pFunc;
pParmWIN32->parm = pParm;
pParmWIN32->epicsPriority = priority;
pParmWIN32->epicsPriority = opts->priority;
{
unsigned threadId;
pParmWIN32->handle = (HANDLE) _beginthreadex (
0, stackSize, epicsWin32ThreadEntry,
0, opts->stackSize, epicsWin32ThreadEntry,
pParmWIN32,
CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
& threadId );
@@ -615,7 +626,7 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
pParmWIN32->id = ( DWORD ) threadId ;
}
osdPriority = epicsThreadGetOsdPriorityValue (priority);
osdPriority = epicsThreadGetOsdPriorityValue (opts->priority);
bstat = SetThreadPriority ( pParmWIN32->handle, osdPriority );
if (!bstat) {
CloseHandle ( pParmWIN32->handle );

View File

@@ -430,15 +430,22 @@ void epicsThreadRealtimeLock(void)
#endif
}
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
{
#if defined (OSITHREAD_USE_DEFAULT_STACK)
return 0;
#define STACK_SIZE(f) (0)
#elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0
#define STACK_SIZE(f) (f * 0x10000 * sizeof(void *))
static const unsigned stackSizeTable[epicsThreadStackBig+1] = {
STACK_SIZE(1), STACK_SIZE(2), STACK_SIZE(4)
};
#else
#define STACK_SIZE(f) (0)
#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
{
#if defined (OSITHREAD_USE_DEFAULT_STACK)
return 0;
#elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0
if (stackSizeClass<epicsThreadStackSmall) {
errlogPrintf("epicsThreadGetStackSize illegal argument (too small)");
return stackSizeTable[epicsThreadStackBig];
@@ -454,6 +461,13 @@ epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadSt
return 0;
#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
}
static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, STACK_SIZE(1)};
void epicsThreadOptsDefaults(epicsThreadOpts *opts)
{
*opts = opts_default;
}
epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
{
@@ -496,19 +510,22 @@ epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
}
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm)
epicsThreadId
epicsThreadCreateOpt (
const char * name,
EPICSTHREADFUNC funptr, void * parm, const epicsThreadOpts *opts )
{
epicsThreadOSD *pthreadInfo;
int status;
sigset_t blockAllSig, oldSig;
if(!opts) opts = &opts_default;
epicsThreadInit();
assert(pcommonAttr);
sigfillset(&blockAllSig);
pthread_sigmask(SIG_SETMASK,&blockAllSig,&oldSig);
pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm);
pthreadInfo = init_threadInfo(name,opts->priority,opts->stackSize,funptr,parm);
if(pthreadInfo==0) return 0;
pthreadInfo->isEpicsThread = 1;
setSchedulingPolicy(pthreadInfo,SCHED_FIFO);
@@ -518,7 +535,7 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
if(status==EPERM){
/* Try again without SCHED_FIFO*/
free_threadInfo(pthreadInfo);
pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm);
pthreadInfo = init_threadInfo(name,opts->priority,opts->stackSize,funptr,parm);
if(pthreadInfo==0) return 0;
pthreadInfo->isEpicsThread = 1;
status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr,

View File

@@ -133,6 +133,13 @@ unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
return stackSizeTable[stackSizeClass];
}
static const epicsThreadOpts opts_default = {epicsThreadPriorityLow, 4000*ARCH_STACK_FACTOR};
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
@@ -190,19 +197,22 @@ static void createFunction(EPICSTHREADFUNC func, void *parm)
#else
#define TASK_FLAGS (VX_FP_TASK)
#endif
epicsThreadId epicsThreadCreate(const char *name,
unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm)
epicsThreadId
epicsThreadCreateOpt (
const char * name,
EPICSTHREADFUNC funptr, void * parm, const epicsThreadOpts *opts )
{
int tid;
if(!opts) opts = &opts_default;
epicsThreadInit();
if(stackSize<100) {
errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize);
if(opts->stackSize<100) {
errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,opts->stackSize);
return(0);
}
tid = taskSpawn((char *)name,getOssPriorityValue(priority),
TASK_FLAGS, stackSize,
tid = taskSpawn((char *)name,getOssPriorityValue(opts->priority),
TASK_FLAGS, opts->stackSize,
(FUNCPTR)createFunction,(int)funptr,(int)parm,
0,0,0,0,0,0,0,0);
if(tid==ERROR) {