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:
@@ -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 {}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user