From 82484b69872e4888767395b4d8452e63a154ef77 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 9 Jan 2023 11:46:17 -0800 Subject: [PATCH] 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. --- modules/libcom/src/osi/epicsThread.cpp | 35 ------------------- modules/libcom/src/osi/os/Linux/osdThread.h | 1 + .../libcom/src/osi/os/RTEMS-score/osdThread.c | 32 +++++++++++++++-- modules/libcom/src/osi/os/WIN32/osdThread.c | 16 +++++++++ modules/libcom/src/osi/os/posix/osdThread.c | 15 ++++++++ modules/libcom/src/osi/os/posix/osdThread.h | 1 + modules/libcom/src/osi/os/vxWorks/osdThread.c | 30 +++++++++++++++- 7 files changed, 91 insertions(+), 39 deletions(-) diff --git a/modules/libcom/src/osi/epicsThread.cpp b/modules/libcom/src/osi/epicsThread.cpp index b1273fd551..5de8fd99b7 100644 --- a/modules/libcom/src/osi/epicsThread.cpp +++ b/modules/libcom/src/osi/epicsThread.cpp @@ -339,32 +339,6 @@ void epicsThread :: show ( unsigned level ) const throw () } 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 ( const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr,void *parm) @@ -375,12 +349,3 @@ extern "C" { return id; } } // 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(); diff --git a/modules/libcom/src/osi/os/Linux/osdThread.h b/modules/libcom/src/osi/os/Linux/osdThread.h index 4bf7f29a67..a691b7ad6d 100644 --- a/modules/libcom/src/osi/os/Linux/osdThread.h +++ b/modules/libcom/src/osi/os/Linux/osdThread.h @@ -37,6 +37,7 @@ typedef struct epicsThreadOSD { int isRealTimeScheduled; int isOnThreadList; int isRunning; + int isOkToBlock; unsigned int osiPriority; int joinable; char name[1]; /* actually larger */ diff --git a/modules/libcom/src/osi/os/RTEMS-score/osdThread.c b/modules/libcom/src/osi/os/RTEMS-score/osdThread.c index 7d37bbe481..b2610ae348 100644 --- a/modules/libcom/src/osi/os/RTEMS-score/osdThread.c +++ b/modules/libcom/src/osi/os/RTEMS-score/osdThread.c @@ -54,6 +54,7 @@ struct taskVar { int refcnt; int joinable; int isRunning; + int isOkToBlock; EPICSTHREADFUNC funptr; void *parm; unsigned int threadVariableCapacity; @@ -226,7 +227,7 @@ void epicsThreadExitMain (void) static rtems_status_code setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr, - void *parm, int joinable) + void *parm, int joinable, int isOkToBlock) { struct taskVar *v; uint32_t note; @@ -242,6 +243,7 @@ setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr, v->threadVariableCapacity = 0; v->threadVariables = NULL; v->isRunning = 1; + v->isOkToBlock = isOkToBlock; if (joinable) { char c[3]; strncpy(c, v->name, 3); @@ -293,7 +295,7 @@ epicsThreadInit (void) if (!onceMutex || !taskVarMutex) cantProceed("epicsThreadInit() can't create global mutexes\n"); 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_"); osdThreadHooksRunMain((epicsThreadId)tid); initialized = 1; @@ -347,7 +349,7 @@ epicsThreadCreateOpt ( name, rtems_status_text(sc)); return 0; } - sc = setThreadInfo (tid, name, funptr, parm, opts->joinable); + sc = setThreadInfo (tid, name, funptr, parm, opts->joinable, 0); if (sc != RTEMS_SUCCESSFUL) { errlogPrintf ("epicsThreadCreate create failure during setup for %s: %s\n", name, rtems_status_text(sc)); @@ -879,3 +881,27 @@ LIBCOM_API int epicsThreadGetCPUs(void) return 1; #endif } + + +int epicsStdCall epicsThreadIsOkToBlock(void) +{ + uint32_t note = 0; + struct taskVar *v; + + rtems_task_get_note (RTEMS_SELF, RTEMS_NOTEPAD_TASKVAR, ¬e); + 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, ¬e); + v = (void *)note; + + if(v) + v->isOkToBlock = !!isOkToBlock; +} diff --git a/modules/libcom/src/osi/os/WIN32/osdThread.c b/modules/libcom/src/osi/os/WIN32/osdThread.c index d055b9bd95..d95c9971b0 100644 --- a/modules/libcom/src/osi/os/WIN32/osdThread.c +++ b/modules/libcom/src/osi/os/WIN32/osdThread.c @@ -103,6 +103,7 @@ typedef struct epicsThreadOSD { char isSuspended; int joinable; int isRunning; + int isOkToBlock; HANDLE timer; /* waitable timer */ } win32ThreadParam; @@ -586,6 +587,7 @@ static win32ThreadParam * epicsThreadImplicitCreate ( void ) pParm->handle = handle; pParm->id = id; + pParm->isOkToBlock = 1; win32ThreadPriority = GetThreadPriority ( pParm->handle ); assert ( win32ThreadPriority != THREAD_PRIORITY_ERROR_RETURN ); pParm->epicsPriority = epicsThreadGetOsiPriorityValue ( win32ThreadPriority ); @@ -1224,3 +1226,17 @@ void testPriorityMapping () return 0; } #endif + +int epicsStdCall epicsThreadIsOkToBlock(void) +{ + struct epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf(); + + return(pthreadInfo->isOkToBlock); +} + +void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock) +{ + struct epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf(); + + pthreadInfo->isOkToBlock = !!isOkToBlock; +} diff --git a/modules/libcom/src/osi/os/posix/osdThread.c b/modules/libcom/src/osi/os/posix/osdThread.c index 6142e73c52..7da2d0074c 100644 --- a/modules/libcom/src/osi/os/posix/osdThread.c +++ b/modules/libcom/src/osi/os/posix/osdThread.c @@ -658,6 +658,7 @@ static epicsThreadOSD *createImplicit(void) assert(pthreadInfo); pthreadInfo->tid = tid; pthreadInfo->osiPriority = 0; + pthreadInfo->isOkToBlock = 1; #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 if(pthread_getschedparam(tid,&pthreadInfo->schedPolicy,&pthreadInfo->schedParam) == 0) { @@ -1058,3 +1059,17 @@ LIBCOM_API int epicsThreadGetCPUs(void) #endif return 1; } + +int epicsStdCall epicsThreadIsOkToBlock(void) +{ + epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf(); + + return(pthreadInfo->isOkToBlock); +} + +void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock) +{ + epicsThreadOSD *pthreadInfo = epicsThreadGetIdSelf(); + + pthreadInfo->isOkToBlock = !!isOkToBlock; +} diff --git a/modules/libcom/src/osi/os/posix/osdThread.h b/modules/libcom/src/osi/os/posix/osdThread.h index ea49030a32..ceb72fb1f6 100644 --- a/modules/libcom/src/osi/os/posix/osdThread.h +++ b/modules/libcom/src/osi/os/posix/osdThread.h @@ -35,6 +35,7 @@ typedef struct epicsThreadOSD { int isRealTimeScheduled; int isOnThreadList; int isRunning; + int isOkToBlock; unsigned int osiPriority; int joinable; char name[1]; /* actually larger */ diff --git a/modules/libcom/src/osi/os/vxWorks/osdThread.c b/modules/libcom/src/osi/os/vxWorks/osdThread.c index c7cc2f5eb8..59e576cebd 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdThread.c +++ b/modules/libcom/src/osi/os/vxWorks/osdThread.c @@ -127,7 +127,8 @@ static void epicsThreadInit(void) taskIdListSize = ID_LIST_CHUNK; atRebootRegister(); ALLOT_JOIN(0); - done = 1; + done = 1; /* avoids recursive call */ + epicsThreadSetOkToBlock(1); } lock = 0; } @@ -577,3 +578,30 @@ LIBCOM_API int epicsThreadGetCPUs(void) { 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); +}