15 #define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h> 26 #include <taskVarLib.h> 37 #ifdef EPICS_THREAD_CAN_JOIN 42 #include <taskUtilLib.h> 44 #define JOIN_WARNING_TIMEOUT (60 * sysClkRateGet()) 46 static SPARE_NUM joinField;
47 #define ALLOT_JOIN(tid) taskSpareNumAllot(tid, &joinField) 49 #define ALLOT_JOIN(tid) 55 #if CPU_FAMILY == MC680X0 56 #define ARCH_STACK_FACTOR 1 57 #elif CPU_FAMILY == SPARC 58 #define ARCH_STACK_FACTOR 2 60 #define ARCH_STACK_FACTOR 2 66 #define ID_LIST_CHUNK 512 67 static int *taskIdList = 0;
69 static SEM_ID epicsThreadListMutex = 0;
75 static void **papTSD = 0;
76 static int nepicsThreadPrivate = 0;
78 static SEM_ID epicsThreadOnceMutex = 0;
85 static unsigned int getOsiPriorityValue(
int ossPriority)
87 if ( ossPriority < 100 ) {
90 else if ( ossPriority > 199 ) {
94 return ( 199u - (
unsigned int) ossPriority );
98 static int getOssPriorityValue(
unsigned int osiPriority)
100 if ( osiPriority > 99 ) {
104 return ( 199 - (
signed int) osiPriority );
108 #define THREAD_SEM_FLAGS (SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY) 109 static void epicsThreadInit(
void)
121 assert(epicsThreadOnceMutex);
123 assert(epicsThreadListMutex);
141 errlogPrintf(
"epicsThreadGetStackSize illegal argument (too small)");
146 errlogPrintf(
"epicsThreadGetStackSize illegal argument (too large)");
150 return stackSizeTable[stackSizeClass];
162 #define EPICS_THREAD_ONCE_DONE &threadOnceComplete 166 result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
171 semGive(epicsThreadOnceMutex);
173 result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
177 semGive(epicsThreadOnceMutex);
178 cantProceed(
"Recursive epicsThreadOnce() initialization\n");
182 semGive(epicsThreadOnceMutex);
184 result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
188 semGive(epicsThreadOnceMutex);
191 #ifdef EPICS_THREAD_CAN_JOIN 196 void epicsThreadAwaitingJoin(
int tid)
198 SEM_ID joinSem = (SEM_ID) taskSpareFieldGet(tid, joinField);
201 if (!joinSem || (
int) joinSem == ERROR)
205 status = semTake(joinSem, JOIN_WARNING_TIMEOUT);
206 if (status && errno == S_objLib_OBJ_TIMEOUT) {
207 errlogPrintf(
"Warning: epicsThread '%s' still awaiting join\n",
209 status = semTake(joinSem, WAIT_FOREVER);
212 perror(
"epicsThreadAwaitingJoin");
214 taskSpareFieldSet(tid, joinField, 0);
217 #define PREPARE_JOIN(tid, joinable) \ 218 taskSpareFieldSet(tid, joinField, \ 219 joinable ? (int) semBCreate(SEM_Q_FIFO, SEM_EMPTY) : 0) 220 #define AWAIT_JOIN(tid) \ 221 epicsThreadAwaitingJoin(tid) 225 #define PREPARE_JOIN(tid, joinable) 226 #define AWAIT_JOIN(tid) 232 int tid = taskIdSelf();
234 taskVarAdd(tid,(
int *)(
char *)&papTSD);
243 taskVarDelete(tid,(
int *)(
char *)&papTSD);
249 #define TASK_FLAGS (VX_FP_TASK | VX_ALTIVEC_TASK) 251 #define TASK_FLAGS (VX_FP_TASK) 256 unsigned int stackSize;
263 opts = &opts_default;
269 if (stackSize < 100) {
270 errlogPrintf(
"epicsThreadCreate %s illegal stackSize %d\n",
275 tid = taskCreate((
char *)name,getOssPriorityValue(opts->
priority),
281 name, strerror(errno));
293 #ifdef EPICS_THREAD_CAN_JOIN 294 const char *
fn =
"epicsThreadMustJoin";
302 joinSem = (SEM_ID) taskSpareFieldGet(tid, joinField);
303 if ((
int) joinSem == ERROR) {
304 errlogPrintf(
"%s: Thread %#x no longer exists.\n", fn, tid);
308 if (tid == taskIdSelf()) {
310 taskSpareFieldSet(tid, joinField, 0);
314 errlogPrintf(
"%s: Thread '%s' (%#x) can't self-join.\n",
321 cantProceed(
"%s: Thread '%s' (%#x) is not joinable.\n",
322 fn, taskName(tid), tid);
328 status = taskWait(tid, WAIT_FOREVER);
329 if (status && errno != S_objLib_OBJ_ID_ERROR) {
340 status = taskSuspend(taskIdSelf());
341 if(status)
errlogPrintf(
"epicsThreadSuspendSelf failed\n");
349 status = taskResume(tid);
355 errlogPrintf(
"epicsThreadExitMain was called for vxWorks. Why?\n");
364 status = taskPriorityGet(tid,&priority);
365 if(status)
errlogPrintf(
"epicsThreadGetPriority failed\n");
366 return(getOsiPriorityValue(priority));
380 priority = getOssPriorityValue(osip);
381 status = taskPrioritySet(tid,priority);
382 if(status)
errlogPrintf(
"epicsThreadSetPriority failed\n");
386 unsigned int priority,
unsigned *pPriorityJustBelow)
388 unsigned newPriority = priority - 1;
389 if (newPriority <= 99) {
390 *pPriorityJustBelow = newPriority;
397 unsigned int priority,
unsigned *pPriorityJustAbove)
399 unsigned newPriority = priority + 1;
401 newPriority = priority + 1;
402 if (newPriority <= 99) {
403 *pPriorityJustAbove = newPriority;
411 return((id1==id2) ? 1 : 0);
417 return((
int)taskIsSuspended(tid));
427 seconds += 0.99999999;
428 ticks = (seconds >= INT_MAX) ? INT_MAX : (
int) seconds;
433 status = taskDelay(ticks);
444 int tid = taskNameToId((
char *)name);
450 return taskName(taskIdSelf());
456 strncpy(name,taskName(tid),size-1);
466 result = semTake(epicsThreadListMutex, WAIT_FOREVER);
468 while (noTasks == 0) {
477 for (i = 0; i < noTasks; i++) {
480 semGive(epicsThreadListMutex);
492 if (level > 1) level = 1;
494 taskShow(tid, level);
516 while(!vxTas(&lock)) taskDelay(1);
534 int int_id = (int)
id;
535 int nepicsThreadPrivateOld = 0;
537 if (papTSD) nepicsThreadPrivateOld = (int)papTSD[0];
539 if (!papTSD || nepicsThreadPrivateOld < int_id) {
540 void **papTSDold = papTSD;
544 "epicsThreadPrivateSet");
545 papTSD[0] = (
void *)(int_id);
546 for (i = 1; i <= nepicsThreadPrivateOld; i++) {
547 papTSD[
i] = papTSDold[
i];
551 papTSD[int_id] = pvt;
556 int int_id = (int)
id;
562 if ( papTSD && int_id <= (
int) papTSD[0] ) {
563 return papTSD[int_id];
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass stackSizeClass)
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadHighestPriorityLevelBelow(unsigned int priority, unsigned *pPriorityJustBelow)
LIBCOM_API int epicsThreadGetCPUs(void)
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate(void)
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
LIBCOM_API void epicsStdCall epicsThreadExitMain(void)
#define assert(exp)
Declare that a condition should be true.
#define EPICS_THREAD_ONCE_DONE
An EPICS-specific replacement for ANSI C's assert.
#define PREPARE_JOIN(tid, joinable)
LIBCOM_API void epicsExitCallAtThreadExits(void)
Internal routine that runs the registered thread exit routines.
LIBCOM_API void epicsThreadRealtimeLock(void)
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum()
Query a value approximating the OS timer/scheduler resolution.
void(* EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id)
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadLowestPriorityLevelAbove(unsigned int priority, unsigned *pPriorityJustAbove)
LIBCOM_API void epicsStdCall epicsThreadPrivateSet(epicsThreadPrivateId id, void *value)
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
A doubly-linked list library.
#define EPICS_THREAD_ONCE_INIT
epicsThreadStackSizeClass
struct epicsThreadPrivateOSD * epicsThreadPrivateId
void epicsThreadEntry(EPICSTHREADFUNC func, void *parm)
#define epicsThreadPriorityMax
LIBCOM_API void epicsStdCall * epicsThreadPrivateGet(epicsThreadPrivateId id)
epicsThreadId epicsThreadCreateOpt(const char *name, EPICSTHREADFUNC funptr, void *parm, const epicsThreadOpts *opts)
Allocate and start a new OS thread.
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPrioritySelf(void)
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetId(const char *name)
void atRebootRegister(void)
Extended replacement for the Posix exit and atexit routines.
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf(void)
LIBCOM_API void epicsStdCall epicsThreadShow(epicsThreadId showThread, unsigned int level)
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
LIBCOM_API int epicsStdCall epicsThreadIsSuspended(epicsThreadId pthreadInfo)
int errlogPrintf(const char *pFormat,...)
LIBCOM_API void epicsStdCall epicsThreadResume(epicsThreadOSD *pthreadInfo)
LIBCOM_API void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func)
const ChannelProviderRegistry::factoryfn_t fn
#define ARCH_STACK_FACTOR
LIBCOM_API void epicsStdCall epicsThreadShowAll(unsigned int level)
#define EPICS_THREAD_OPTS_INIT
LIBCOM_API void cantProceed(const char *msg,...)
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPriority(epicsThreadId pthreadInfo)
void epicsThreadMustJoin(epicsThreadId id)
Routines for code that can't continue or return after an error.
LIBCOM_API void osdThreadHooksRun(epicsThreadId id)
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
LIBCOM_API void epicsStdCall epicsThreadSetPriority(epicsThreadId pthreadInfo, unsigned int priority)
C++ and C descriptions for a thread.
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete(epicsThreadPrivateId id)
#define epicsThreadPriorityMin
void(* EPICSTHREADFUNC)(void *parm)
LIBCOM_API const char epicsStdCall * epicsThreadGetNameSelf()
LIBCOM_API int epicsStdCall epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2)
LIBCOM_API void epicsStdCall epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size)