26 #if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 46 static int mutexLock(pthread_mutex_t *
id)
51 status = pthread_mutex_lock(
id);
52 if(status!=EINTR)
return status;
53 fprintf(
stderr,
"pthread_mutex_lock returned EINTR. Violates SUSv3\n");
57 #if defined DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING 58 #undef _POSIX_THREAD_PRIORITY_SCHEDULING 70 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 78 static pthread_key_t getpthreadInfo;
79 static pthread_mutex_t onceLock;
80 static pthread_mutex_t listLock;
83 static int epicsThreadOnceCalled = 0;
87 #define checkStatus(status,message) \ 89 errlogPrintf("%s error %s\n",(message),strerror((status))); \ 92 #define checkStatusQuit(status,message,method) \ 94 errlogPrintf("%s error %s\n",(message),strerror((status))); \ 95 cantProceed((method)); \ 102 #define checkStatusOnce(status,message) \ 104 fprintf(stderr,"%s error %s\n",(message),strerror((status))); } 106 #define checkStatusOnceQuit(status,message,method) \ 108 fprintf(stderr,"%s error %s",(message),strerror((status))); \ 109 fprintf(stderr," %s\n",method); \ 110 fprintf(stderr,"epicsThreadInit cant proceed. Program exiting\n"); \ 117 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 125 oss = (double)pthreadInfo->
osiPriority * slope + minPriority;
132 static void setSchedulingPolicy(
epicsThreadOSD *pthreadInfo,
int policy)
134 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 139 status = pthread_attr_getschedparam(
144 status = pthread_attr_setschedpolicy(
145 &pthreadInfo->
attr,policy);
147 status = pthread_attr_setschedparam(
150 status = pthread_attr_setinheritsched(
151 &pthreadInfo->
attr,PTHREAD_EXPLICIT_SCHED);
161 pthreadInfo = calloc(1,
sizeof(*pthreadInfo) + strlen(name));
169 strcpy(pthreadInfo->
name, name);
175 unsigned int priority,
unsigned int stackSize,
182 pthreadInfo = create_threadInfo(name);
188 status = pthread_attr_init(&pthreadInfo->
attr);
192 status = pthread_attr_setdetachstate(
193 &pthreadInfo->
attr, PTHREAD_CREATE_DETACHED);
196 #if defined (_POSIX_THREAD_ATTR_STACKSIZE) 197 #if ! defined (OSITHREAD_USE_DEFAULT_STACK) 198 status = pthread_attr_setstacksize( &pthreadInfo->
attr,(
size_t)stackSize);
202 status = pthread_attr_setscope(&pthreadInfo->
attr,PTHREAD_SCOPE_PROCESS);
214 status = mutexLock(&listLock);
217 status = pthread_mutex_unlock(&listLock);
220 status = pthread_attr_destroy(&pthreadInfo->
attr);
225 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 233 static int try_pri(
int pri,
int policy)
235 struct sched_param schedp;
237 schedp.sched_priority = pri;
238 return pthread_setschedparam(pthread_self(), policy, &schedp);
242 find_pri_range(
void *arg)
244 priAvailable *prm = arg;
245 int min = sched_get_priority_min(prm->policy);
246 int max = sched_get_priority_max(prm->policy);
249 if ( -1 == min || -1 == max ) {
256 prm->min_pri = prm->max_pri = -1;
261 if ( try_pri(min, prm->policy) ) {
272 prm->min_pri = prm->max_pri =
min;
284 while ( low < max ) {
286 if ( try_pri(
try, prm->policy) ) {
294 prm->max_pri = try_pri(max, prm->policy) ? max-1 :
max;
300 static void findPriorityRange(
commonAttr *a_p)
310 status = pthread_create(&
id, 0, find_pri_range, &arg);
313 status = pthread_join(
id, &dummy);
323 static void once(
void)
328 pthread_key_create(&getpthreadInfo,0);
329 status = pthread_mutex_init(&onceLock,0);
331 status = pthread_mutex_init(&listLock,0);
335 status = pthread_attr_init(&pcommonAttr->
attr);
337 status = pthread_attr_setdetachstate(
338 &pcommonAttr->
attr, PTHREAD_CREATE_DETACHED);
340 status = pthread_attr_setscope(&pcommonAttr->
attr,PTHREAD_SCOPE_PROCESS);
343 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 344 status = pthread_attr_setschedpolicy(
345 &pcommonAttr->
attr,SCHED_FIFO);
347 status = pthread_attr_getschedpolicy(
350 status = pthread_attr_getschedparam(
354 findPriorityRange(pcommonAttr);
358 fprintf(
stderr,
"sched_get_priority_max failed set to %d\n",
363 fprintf(
stderr,
"sched_get_priority_min failed set to %d\n",
368 fprintf(
stderr,
"LRT: min priority: %d max priority %d\n",
378 status = pthread_setspecific(getpthreadInfo,(
void *)pthreadInfo);
380 status = mutexLock(&listLock);
384 status = pthread_mutex_unlock(&listLock);
389 epicsThreadOnceCalled = 1;
392 static void * start_routine(
void *arg)
396 sigset_t blockAllSig;
398 sigfillset(&blockAllSig);
399 pthread_sigmask(SIG_SETMASK,&blockAllSig,
NULL);
400 status = pthread_setspecific(getpthreadInfo,arg);
402 status = mutexLock(&listLock);
406 status = pthread_mutex_unlock(&listLock);
413 free_threadInfo(pthreadInfo);
417 static void epicsThreadInit(
void)
419 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
420 int status = pthread_once(&once_control,once);
427 #if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 429 int status = mlockall(MCL_CURRENT | MCL_FUTURE);
432 const int err = errno;
436 fprintf(
stderr,
"epicsThreadRealtimeLock " 437 "Warning: unable to lock memory. RLIMIT_MEMLOCK is too small or missing CAP_IPC_LOCK\n");
440 fprintf(
stderr,
"epicsThreadRealtimeLock " 441 "Warning: unable to lock memory. missing CAP_IPC_LOCK\n");
445 fprintf(
stderr,
"epicsThreadRealtimeLock " 446 "Warning: Unable to lock the virtual address space.\n" 447 "VM page faults may harm real-time performance. errno=%d\n",
455 #if defined (OSITHREAD_USE_DEFAULT_STACK) 456 #define STACK_SIZE(f) (0) 457 #elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0 458 #define STACK_SIZE(f) (f * 0x10000 * sizeof(void *)) 463 #define STACK_SIZE(f) (0) 468 #if defined (OSITHREAD_USE_DEFAULT_STACK) 470 #elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0 472 errlogPrintf(
"epicsThreadGetStackSize illegal argument (too small)");
477 errlogPrintf(
"epicsThreadGetStackSize illegal argument (too large)");
481 return stackSizeTable[stackSizeClass];
490 #define EPICS_THREAD_ONCE_DONE &threadOnceComplete 494 status = mutexLock(&onceLock);
496 fprintf(
stderr,
"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
504 status = pthread_mutex_unlock(&onceLock);
507 status = mutexLock(&onceLock);
511 status = pthread_mutex_unlock(&onceLock);
513 cantProceed(
"Recursive epicsThreadOnce() initialization\n");
517 status = pthread_mutex_unlock(&onceLock);
520 status = mutexLock(&onceLock);
524 status = pthread_mutex_unlock(&onceLock);
532 unsigned int stackSize;
535 sigset_t blockAllSig, oldSig;
542 opts = &opts_default;
548 sigfillset(&blockAllSig);
549 pthread_sigmask(SIG_SETMASK, &blockAllSig, &oldSig);
551 pthreadInfo = init_threadInfo(name, opts->
priority, stackSize, funptr,
557 setSchedulingPolicy(pthreadInfo, SCHED_FIFO);
565 status = pthread_create(&pthreadInfo->
tid, &pthreadInfo->
attr,
566 start_routine, pthreadInfo);
569 free_threadInfo(pthreadInfo);
571 pthreadInfo = init_threadInfo(name, opts->
priority, stackSize,
577 status = pthread_create(&pthreadInfo->
tid, &pthreadInfo->
attr,
578 start_routine, pthreadInfo);
587 free_threadInfo(pthreadInfo);
591 status = pthread_sigmask(SIG_SETMASK, &oldSig,
NULL);
606 tid = pthread_self();
607 sprintf(name,
"non-EPICS_%ld", (
long)tid);
608 pthreadInfo = create_threadInfo(name);
613 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 623 status = pthread_setspecific(getpthreadInfo,(
void *)pthreadInfo);
624 checkStatus(status,
"pthread_setspecific createImplicit");
626 free_threadInfo(pthreadInfo);
653 status = pthread_join(id->
tid, &ret);
654 if(status == EDEADLK) {
658 status = pthread_detach(id->
tid);
669 pthreadInfo = (
epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
670 if(pthreadInfo==
NULL)
671 pthreadInfo = createImplicit();
678 assert(epicsThreadOnceCalled);
688 pthreadInfo = (
epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
689 if(pthreadInfo==
NULL)
690 pthreadInfo = createImplicit();
696 free_threadInfo(pthreadInfo);
703 assert(epicsThreadOnceCalled);
715 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 719 assert(epicsThreadOnceCalled);
722 fprintf(
stderr,
"epicsThreadSetPriority called by non epics thread\n");
728 #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 731 status = pthread_attr_setschedparam(
734 status = pthread_setschedparam(
741 unsigned int priority,
unsigned *pPriorityJustBelow)
743 unsigned newPriority = priority - 1;
744 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 747 if(diff<0) diff = -diff;
748 if(diff>1 && diff <100) newPriority -= 100/(diff+1);
750 if (newPriority <= 99) {
751 *pPriorityJustBelow = newPriority;
758 unsigned int priority,
unsigned *pPriorityJustAbove)
760 unsigned newPriority = priority + 1;
762 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 765 if(diff<0) diff = -diff;
766 if(diff>1 && diff <100) newPriority += 100/(diff+1);
769 if (newPriority <= 99) {
770 *pPriorityJustAbove = newPriority;
778 assert(epicsThreadOnceCalled);
781 return(pthread_equal(p1->
tid,p2->
tid));
785 assert(epicsThreadOnceCalled);
797 delayTime.
tv_sec = seconds;
798 nanoseconds = (seconds - delayTime.
tv_sec) *1e9;
799 delayTime.
tv_nsec = nanoseconds;
805 while (nanosleep(&delayTime, &remainingTime) == -1 &&
807 delayTime = remainingTime;
814 pthreadInfo = (
epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
815 if(pthreadInfo==
NULL)
816 pthreadInfo = createImplicit();
823 return threadId->
tid;
830 assert(epicsThreadOnceCalled);
831 status = mutexLock(&listLock);
832 checkStatus(status,
"pthread_mutex_lock epicsThreadGetId");
837 if(strcmp(name,pthreadInfo->
name) == 0)
break;
840 status = pthread_mutex_unlock(&listLock);
841 checkStatus(status,
"pthread_mutex_unlock epicsThreadGetId");
851 pthreadInfo = (
epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
852 if(pthreadInfo==
NULL)
853 pthreadInfo = createImplicit();
854 return(pthreadInfo->
name);
859 assert(epicsThreadOnceCalled);
860 strncpy(name, pthreadInfo->
name, size-1);
870 status = mutexLock(&listLock);
871 checkStatus(status,
"pthread_mutex_lock epicsThreadMap");
875 while (pthreadInfo) {
879 status = pthread_mutex_unlock(&listLock);
880 checkStatus(status,
"pthread_mutex_unlock epicsThreadMap");
890 status = mutexLock(&listLock);
891 checkStatus(status,
"pthread_mutex_lock epicsThreadShowAll");
899 status = pthread_mutex_unlock(&listLock);
900 checkStatus(status,
"pthread_mutex_unlock epicsThreadShowAll");
914 status = mutexLock(&listLock);
915 checkStatus(status,
"pthread_mutex_lock epicsThreadShowAll");
927 status = pthread_mutex_unlock(&listLock);
928 checkStatus(status,
"pthread_mutex_unlock epicsThreadShowAll");
931 printf(
"Thread %#lx (%lu) not found.\n", (
unsigned long)showThread, (
unsigned long)showThread);
940 key = calloc(1,
sizeof(pthread_key_t));
943 status = pthread_key_create(key,0);
944 checkStatus(status,
"pthread_key_create epicsThreadPrivateCreate");
952 pthread_key_t *key = (pthread_key_t *)
id;
955 assert(epicsThreadOnceCalled);
956 status = pthread_key_delete(*key);
957 checkStatusQuit(status,
"pthread_key_delete",
"epicsThreadPrivateDelete");
963 pthread_key_t *key = (pthread_key_t *)
id;
966 assert(epicsThreadOnceCalled);
968 errlogPrintf(
"epicsThreadPrivateSet: setting value of 0\n");
969 status = pthread_setspecific(*key,value);
975 pthread_key_t *key = (pthread_key_t *)
id;
977 assert(epicsThreadOnceCalled);
978 return pthread_getspecific(*key);
984 hz = sysconf ( _SC_CLK_TCK );
993 #ifdef _SC_NPROCESSORS_ONLN 994 ret = sysconf(_SC_NPROCESSORS_ONLN);
998 #ifdef _SC_NPROCESSORS_CONF 999 ret = sysconf(_SC_NPROCESSORS_CONF);
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.
epicsEventId suspendEvent
An EPICS-specific replacement for ANSI C's assert.
LIBCOM_API void epicsExitCallAtThreadExits(void)
Internal routine that runs the registered thread exit routines.
struct sched_param schedParam
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)
#define epicsEventWait(ID)
struct epicsThreadOSD * epicsThreadId
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT(int *pTarget, int oldVal, int newVal)
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadLowestPriorityLevelAbove(unsigned int priority, unsigned *pPriorityJustAbove)
#define ELLLIST_INIT
Value of an empty list.
LIBCOM_API void epicsStdCall epicsThreadPrivateSet(epicsThreadPrivateId id, void *value)
LIBCOM_API void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
#define ellNext(PNODE)
Find the next node in list.
struct commonAttr commonAttr
#define EPICS_THREAD_ONCE_INIT
LIBCOM_API int epicsThreadGetPosixPriority(epicsThreadId pthreadInfo)
epicsThreadStackSizeClass
#define epicsEventSignal(ID)
A synonym for epicsEventTrigger().
APIs for the epicsMutex mutual exclusion semaphore.
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)
#define checkStatus(status, message)
Extended replacement for the Posix exit and atexit routines.
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf(void)
LIBCOM_API void epicsEventDestroy(epicsEventId id)
Destroy an epicsEvent and any resources it holds.
LIBCOM_API void epicsStdCall epicsThreadShow(epicsThreadId showThread, unsigned int level)
LIBCOM_API int epicsStdCall epicsThreadIsSuspended(epicsThreadId pthreadInfo)
int errlogPrintf(const char *pFormat,...)
struct sched_param schedParam
LIBCOM_API void epicsStdCall epicsThreadResume(epicsThreadOSD *pthreadInfo)
APIs for the epicsEvent binary semaphore.
epics::pvData::PVStructurePtr dummy
LIBCOM_API void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func)
EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT(int *pTarget)
LIBCOM_API void osdThreadHooksRunMain(epicsThreadId id)
EPICSTHREADFUNC createFunc
LIBCOM_API void epicsStdCall epicsThreadShowAll(unsigned int level)
#define checkStatusOnce(status, message)
#define EPICS_THREAD_OPTS_INIT
EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT(int *pTarget)
LIBCOM_API void cantProceed(const char *msg,...)
LIBCOM_API void epicsExitCallAtExits(void)
Internal routine that runs the registered exit routines.
LIBCOM_API pthread_t epicsThreadGetPosixThreadId(epicsThreadId threadId)
Defined by POSIX Real Time.
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)
#define checkStatusQuit(status, message, method)
LIBCOM_API void epicsStdCall epicsThreadSetPriority(epicsThreadId pthreadInfo, unsigned int priority)
#define checkStatusOnceQuit(status, message, method)
C++ and C descriptions for a thread.
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete(epicsThreadPrivateId id)
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
LIBCOM_API epicsEventId epicsEventCreate(epicsEventInitialState initialState)
Create an epicsEvent for use from C code, or return NULL.
void(* EPICSTHREADFUNC)(void *parm)
#define EPICS_THREAD_ONCE_DONE
LIBCOM_API const char epicsStdCall * epicsThreadGetNameSelf()
LIBCOM_API int epicsStdCall epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2)
#define ellFirst(PLIST)
Find the first node in list.
LIBCOM_API void epicsStdCall epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size)