Avoid initMainThread() except on vxworks

Move isOkToBlock tracking to osdThread.
Targets except vxworks can store this flag in epicsThreadOSD.
Continue to use TLS w/ vxWorks.

Note that setting of isOkToBlock for "main" thread becomes lazy.
This commit is contained in:
Michael Davidsaver
2023-01-09 11:46:17 -08:00
committed by Andrew Johnson
parent 9f788996dc
commit 48ebe2c64e
7 changed files with 91 additions and 39 deletions

View File

@ -339,32 +339,6 @@ void epicsThread :: show ( unsigned level ) const throw ()
} }
extern "C" { extern "C" {
static epicsThreadOnceId okToBlockOnce = EPICS_THREAD_ONCE_INIT;
epicsThreadPrivateId okToBlockPrivate;
static const int okToBlockNo = 0;
static const int okToBlockYes = 1;
static void epicsThreadOnceIdInit(void *)
{
okToBlockPrivate = epicsThreadPrivateCreate();
}
int epicsStdCall epicsThreadIsOkToBlock(void)
{
const int *pokToBlock;
epicsThreadOnce(&okToBlockOnce, epicsThreadOnceIdInit, NULL);
pokToBlock = (int *) epicsThreadPrivateGet(okToBlockPrivate);
return (pokToBlock ? *pokToBlock : 0);
}
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
{
const int *pokToBlock;
epicsThreadOnce(&okToBlockOnce, epicsThreadOnceIdInit, NULL);
pokToBlock = (isOkToBlock) ? &okToBlockYes : &okToBlockNo;
epicsThreadPrivateSet(okToBlockPrivate, (void *)pokToBlock);
}
epicsThreadId epicsStdCall epicsThreadMustCreate ( epicsThreadId epicsStdCall epicsThreadMustCreate (
const char *name, unsigned int priority, unsigned int stackSize, const char *name, unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm) EPICSTHREADFUNC funptr,void *parm)
@ -375,12 +349,3 @@ extern "C" {
return id; return id;
} }
} // extern "C" } // extern "C"
static epicsThreadId initMainThread(void) {
epicsThreadId main = epicsThreadGetIdSelf();
epicsThreadSetOkToBlock(1);
return main;
}
// Ensure the main thread gets a unique ID and allows blocking I/O
epicsThreadId epicsThreadMainId = initMainThread();

View File

@ -37,6 +37,7 @@ typedef struct epicsThreadOSD {
int isRealTimeScheduled; int isRealTimeScheduled;
int isOnThreadList; int isOnThreadList;
int isRunning; int isRunning;
int isOkToBlock;
unsigned int osiPriority; unsigned int osiPriority;
int joinable; int joinable;
char name[1]; /* actually larger */ char name[1]; /* actually larger */

View File

@ -55,6 +55,7 @@ struct taskVar {
int refcnt; int refcnt;
int joinable; int joinable;
int isRunning; int isRunning;
int isOkToBlock;
EPICSTHREADFUNC funptr; EPICSTHREADFUNC funptr;
void *parm; void *parm;
unsigned int threadVariableCapacity; unsigned int threadVariableCapacity;
@ -219,7 +220,7 @@ void epicsThreadExitMain (void)
static rtems_status_code static rtems_status_code
setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr, setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr,
void *parm, int joinable) void *parm, int joinable, int isOkToBlock)
{ {
struct taskVar *v; struct taskVar *v;
uint32_t note; uint32_t note;
@ -235,6 +236,7 @@ setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr,
v->threadVariableCapacity = 0; v->threadVariableCapacity = 0;
v->threadVariables = NULL; v->threadVariables = NULL;
v->isRunning = 1; v->isRunning = 1;
v->isOkToBlock = isOkToBlock;
if (joinable) { if (joinable) {
char c[3] = {0,0,0}; char c[3] = {0,0,0};
strncpy(c, v->name, 3); strncpy(c, v->name, 3);
@ -284,7 +286,7 @@ epicsThreadInit (void)
epicsMutexOsdPrepare(&taskVarMutex); epicsMutexOsdPrepare(&taskVarMutex);
epicsMutexOsdPrepare(&onceMutex); epicsMutexOsdPrepare(&onceMutex);
rtems_task_ident (RTEMS_SELF, 0, &tid); rtems_task_ident (RTEMS_SELF, 0, &tid);
if(setThreadInfo (tid, "_main_", NULL, NULL, 0) != RTEMS_SUCCESSFUL) if(setThreadInfo (tid, "_main_", NULL, NULL, 0, 1) != RTEMS_SUCCESSFUL)
cantProceed("epicsThreadInit() unable to setup _main_"); cantProceed("epicsThreadInit() unable to setup _main_");
osdThreadHooksRunMain((epicsThreadId)tid); osdThreadHooksRunMain((epicsThreadId)tid);
initialized = 1; initialized = 1;
@ -338,7 +340,7 @@ epicsThreadCreateOpt (
name, rtems_status_text(sc)); name, rtems_status_text(sc));
return 0; return 0;
} }
sc = setThreadInfo (tid, name, funptr, parm, opts->joinable); sc = setThreadInfo (tid, name, funptr, parm, opts->joinable, 0);
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
errlogPrintf ("epicsThreadCreate create failure during setup for %s: %s\n", errlogPrintf ("epicsThreadCreate create failure during setup for %s: %s\n",
name, rtems_status_text(sc)); name, rtems_status_text(sc));
@ -870,3 +872,27 @@ LIBCOM_API int epicsThreadGetCPUs(void)
return 1; return 1;
#endif #endif
} }
int epicsStdCall epicsThreadIsOkToBlock(void)
{
uint32_t note = 0;
struct taskVar *v;
rtems_task_get_note (RTEMS_SELF, RTEMS_NOTEPAD_TASKVAR, &note);
v = (void *)note;
return v && v->isOkToBlock;
}
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
{
uint32_t note = 0;
struct taskVar *v;
rtems_task_get_note (RTEMS_SELF, RTEMS_NOTEPAD_TASKVAR, &note);
v = (void *)note;
if(v)
v->isOkToBlock = !!isOkToBlock;
}

View File

@ -103,6 +103,7 @@ typedef struct epicsThreadOSD {
char isSuspended; char isSuspended;
int joinable; int joinable;
int isRunning; int isRunning;
int isOkToBlock;
HANDLE timer; /* waitable timer */ HANDLE timer; /* waitable timer */
} win32ThreadParam; } win32ThreadParam;
@ -586,6 +587,7 @@ static win32ThreadParam * epicsThreadImplicitCreate ( void )
pParm->handle = handle; pParm->handle = handle;
pParm->id = id; pParm->id = id;
pParm->isOkToBlock = 1;
win32ThreadPriority = GetThreadPriority ( pParm->handle ); win32ThreadPriority = GetThreadPriority ( pParm->handle );
assert ( win32ThreadPriority != THREAD_PRIORITY_ERROR_RETURN ); assert ( win32ThreadPriority != THREAD_PRIORITY_ERROR_RETURN );
pParm->epicsPriority = epicsThreadGetOsiPriorityValue ( win32ThreadPriority ); pParm->epicsPriority = epicsThreadGetOsiPriorityValue ( win32ThreadPriority );
@ -1224,3 +1226,17 @@ void testPriorityMapping ()
return 0; return 0;
} }
#endif #endif
int epicsStdCall epicsThreadIsOkToBlock(void)
{
struct epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf();
return(pthreadInfo->isOkToBlock);
}
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
{
struct epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf();
pthreadInfo->isOkToBlock = !!isOkToBlock;
}

View File

@ -665,6 +665,7 @@ static epicsThreadOSD *createImplicit(void)
assert(pthreadInfo); assert(pthreadInfo);
pthreadInfo->tid = tid; pthreadInfo->tid = tid;
pthreadInfo->osiPriority = 0; pthreadInfo->osiPriority = 0;
pthreadInfo->isOkToBlock = 1;
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
if(pthread_getschedparam(tid,&pthreadInfo->schedPolicy,&pthreadInfo->schedParam) == 0) { if(pthread_getschedparam(tid,&pthreadInfo->schedPolicy,&pthreadInfo->schedParam) == 0) {
@ -1085,3 +1086,17 @@ LIBCOM_API int epicsThreadGetCPUs(void)
#endif #endif
return 1; return 1;
} }
int epicsStdCall epicsThreadIsOkToBlock(void)
{
epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf();
return(pthreadInfo->isOkToBlock);
}
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
{
epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf();
pthreadInfo->isOkToBlock = !!isOkToBlock;
}

View File

@ -35,6 +35,7 @@ typedef struct epicsThreadOSD {
int isRealTimeScheduled; int isRealTimeScheduled;
int isOnThreadList; int isOnThreadList;
int isRunning; int isRunning;
int isOkToBlock;
unsigned int osiPriority; unsigned int osiPriority;
int joinable; int joinable;
char name[1]; /* actually larger */ char name[1]; /* actually larger */

View File

@ -127,7 +127,8 @@ static void epicsThreadInit(void)
taskIdListSize = ID_LIST_CHUNK; taskIdListSize = ID_LIST_CHUNK;
atRebootRegister(); atRebootRegister();
ALLOT_JOIN(0); ALLOT_JOIN(0);
done = 1; done = 1; /* avoids recursive call */
epicsThreadSetOkToBlock(1);
} }
lock = 0; lock = 0;
} }
@ -577,3 +578,30 @@ LIBCOM_API int epicsThreadGetCPUs(void)
{ {
return 1; return 1;
} }
static epicsThreadOnceId okToBlockOnce = EPICS_THREAD_ONCE_INIT;
static epicsThreadPrivateId okToBlockPrivate;
static const int okToBlockNo = 0;
static const int okToBlockYes = 1;
static void epicsThreadOnceIdInit(void *not_used)
{
okToBlockPrivate = epicsThreadPrivateCreate();
}
int epicsStdCall epicsThreadIsOkToBlock(void)
{
const int *pokToBlock;
epicsThreadOnce(&okToBlockOnce, epicsThreadOnceIdInit, NULL);
pokToBlock = (int *) epicsThreadPrivateGet(okToBlockPrivate);
return (pokToBlock ? *pokToBlock : 0);
}
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
{
const int *pokToBlock;
epicsThreadOnce(&okToBlockOnce, epicsThreadOnceIdInit, NULL);
pokToBlock = (isOkToBlock) ? &okToBlockYes : &okToBlockNo;
epicsThreadPrivateSet(okToBlockPrivate, (void *)pokToBlock);
}