This is Unofficial EPICS BASE Doxygen Site
epicsThread.h File Reference

C++ and C descriptions for a thread. More...

#include <stddef.h>
#include "libComAPI.h"
#include "osdThread.h"
+ Include dependency graph for epicsThread.h:

Go to the source code of this file.

Classes

struct  epicsThreadOpts
 

Macros

#define EPICS_THREAD_ONCE_INIT   0
 
#define EPICS_THREAD_OPTS_INIT
 
#define EPICS_THREAD_CAN_JOIN
 
Some Named Thread Priorities
#define epicsThreadPriorityMax   99
 
#define epicsThreadPriorityMin   0
 
#define epicsThreadPriorityLow   10
 
#define epicsThreadPriorityMedium   50
 
#define epicsThreadPriorityHigh   90
 
#define epicsThreadPriorityCAServerLow   20
 
#define epicsThreadPriorityCAServerHigh   40
 
#define epicsThreadPriorityScanLow   60
 
#define epicsThreadPriorityScanHigh   70
 
#define epicsThreadPriorityIocsh   91
 
#define epicsThreadPriorityBaseMax   91
 

Typedefs

typedef void(* EPICSTHREADFUNC) (void *parm)
 
typedef struct epicsThreadOSDepicsThreadId
 
typedef epicsThreadId epicsThreadOnceId
 
typedef struct epicsThreadOpts epicsThreadOpts
 
typedef void(* EPICS_THREAD_HOOK_ROUTINE) (epicsThreadId id)
 
typedef struct epicsThreadPrivateOSDepicsThreadPrivateId
 

Enumerations

enum  epicsThreadStackSizeClass { epicsThreadStackSmall, epicsThreadStackMedium, epicsThreadStackBig }
 
enum  epicsThreadBooleanStatus { epicsThreadBooleanStatusFail, epicsThreadBooleanStatusSuccess }
 

Functions

LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize (epicsThreadStackSizeClass size)
 
LIBCOM_API void epicsStdCall epicsThreadOnce (epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
 
LIBCOM_API void epicsThreadRealtimeLock (void)
 
LIBCOM_API void epicsStdCall epicsThreadExitMain (void)
 
LIBCOM_API epicsThreadId epicsThreadCreateOpt (const char *name, EPICSTHREADFUNC funptr, void *parm, const epicsThreadOpts *opts)
 Allocate and start a new OS thread. More...
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadCreate (const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadMustCreate (const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
 
LIBCOM_API void epicsThreadMustJoin (epicsThreadId id)
 
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf (void)
 
LIBCOM_API void epicsStdCall epicsThreadResume (epicsThreadId id)
 
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPriority (epicsThreadId id)
 
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPrioritySelf (void)
 
LIBCOM_API void epicsStdCall epicsThreadSetPriority (epicsThreadId id, unsigned int priority)
 
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadHighestPriorityLevelBelow (unsigned int priority, unsigned *pPriorityJustBelow)
 
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadLowestPriorityLevelAbove (unsigned int priority, unsigned *pPriorityJustAbove)
 
LIBCOM_API int epicsStdCall epicsThreadIsEqual (epicsThreadId id1, epicsThreadId id2)
 
LIBCOM_API int epicsStdCall epicsThreadIsSuspended (epicsThreadId id)
 
LIBCOM_API void epicsStdCall epicsThreadSleep (double seconds)
 Block the calling thread for at least the specified time. More...
 
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum (void)
 Query a value approximating the OS timer/scheduler resolution. More...
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf (void)
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetId (const char *name)
 
LIBCOM_API int epicsThreadGetCPUs (void)
 
LIBCOM_API const char *epicsStdCall epicsThreadGetNameSelf (void)
 
LIBCOM_API void epicsStdCall epicsThreadGetName (epicsThreadId id, char *name, size_t size)
 
LIBCOM_API int epicsStdCall epicsThreadIsOkToBlock (void)
 
LIBCOM_API void epicsStdCall epicsThreadSetOkToBlock (int isOkToBlock)
 
LIBCOM_API void epicsStdCall epicsThreadShowAll (unsigned int level)
 
LIBCOM_API void epicsStdCall epicsThreadShow (epicsThreadId id, unsigned int level)
 
LIBCOM_API int epicsThreadHookAdd (EPICS_THREAD_HOOK_ROUTINE hook)
 
LIBCOM_API int epicsThreadHookDelete (EPICS_THREAD_HOOK_ROUTINE hook)
 
LIBCOM_API void epicsThreadHooksShow (void)
 
LIBCOM_API void epicsThreadMap (EPICS_THREAD_HOOK_ROUTINE func)
 
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate (void)
 
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete (epicsThreadPrivateId id)
 
LIBCOM_API void epicsStdCall epicsThreadPrivateSet (epicsThreadPrivateId, void *)
 
LIBCOM_API void *epicsStdCall epicsThreadPrivateGet (epicsThreadPrivateId)
 

Detailed Description

C++ and C descriptions for a thread.

The epicsThread API is meant as a somewhat minimal interface for multithreaded applications. It can be implementedon a wide variety of systems with the restriction that the system MUST support a multithreaded environment. A POSIX pthreads version is provided.

The interface provides the following thread facilities, with restrictions as noted:

  • Life cycle: a thread starts life as a result of a call to epicsThreadCreate. It terminates when the thread function returns. It should not return until it has released all resources it uses. If a thread is expected to terminate as a natural part of its life cycle then the thread function must return.
  • epicsThreadOnce: this provides the ability to have an initialization function that is guaranteed to be called exactly once.
  • main: if a main routine finishes its work but wants to leave other threads running it can call epicsThreadExitMain, which should be the last statement in main.
  • Priorities: ranges between 0 and 99 with a higher number meaning higher priority. A number of constants are defined for iocCore specific threads. The underlying implementation may collapse the range 0 to 99 into a smaller range; even a single priority. User code should never rely on the existence of multiple thread priorities to guarantee correct behavior.
  • Stack Size: epicsThreadCreate accepts a stack size parameter. Three generic sizes are available: small, medium,and large. Portable code should always use one of the generic sizes. Some implementation may ignore the stack size request and use a system default instead. Virtual memory systems providing generous stack sizes can be expected to use the system default.
  • epicsThreadId: every epicsThread has an Id which gets returned by epicsThreadCreate and is valid as long as that thread still exists. A value of 0 always means no thread. If a threadId is used after the thread has terminated,the results are not defined (but will normally lead to bad things happening). Thus code that looks after other threads MUST be aware of threads terminating.

Definition in file epicsThread.h.

Macro Definition Documentation

#define EPICS_THREAD_CAN_JOIN

Definition at line 193 of file epicsThread.h.

#define EPICS_THREAD_ONCE_INIT   0

Definition at line 109 of file epicsThread.h.

#define EPICS_THREAD_OPTS_INIT
Value:

Default initial values for epicsThreadOpts Applications should always use this macro to initialize an epicsThreadOpts structure. Additional fields may be added in the future, and the order of the fields might also change, thus code that assumes the above definition might break if these rules are not followed.

Definition at line 167 of file epicsThread.h.

#define epicsThreadPriorityBaseMax   91

Definition at line 85 of file epicsThread.h.

#define epicsThreadPriorityCAServerHigh   40

Definition at line 81 of file epicsThread.h.

#define epicsThreadPriorityCAServerLow   20

Definition at line 80 of file epicsThread.h.

#define epicsThreadPriorityHigh   90

Definition at line 77 of file epicsThread.h.

#define epicsThreadPriorityIocsh   91

Definition at line 84 of file epicsThread.h.

#define epicsThreadPriorityLow   10

Definition at line 75 of file epicsThread.h.

#define epicsThreadPriorityMax   99

Definition at line 71 of file epicsThread.h.

#define epicsThreadPriorityMedium   50

Definition at line 76 of file epicsThread.h.

#define epicsThreadPriorityMin   0

Definition at line 72 of file epicsThread.h.

#define epicsThreadPriorityScanHigh   70

Definition at line 83 of file epicsThread.h.

#define epicsThreadPriorityScanLow   60

Definition at line 82 of file epicsThread.h.

Typedef Documentation

typedef void(* EPICS_THREAD_HOOK_ROUTINE) (epicsThreadId id)

Hooks called when a thread starts, map function called once for every thread.

Definition at line 302 of file epicsThread.h.

typedef void(* EPICSTHREADFUNC) (void *parm)

Definition at line 66 of file epicsThread.h.

typedef struct epicsThreadOSD* epicsThreadId

(epicsThreadId)0 is guaranteed to be an invalid thread id

Definition at line 106 of file epicsThread.h.

Definition at line 108 of file epicsThread.h.

Thread local storage

Definition at line 328 of file epicsThread.h.

Enumeration Type Documentation

Enumerator
epicsThreadBooleanStatusFail 
epicsThreadBooleanStatusSuccess 

Definition at line 93 of file epicsThread.h.

Stack sizes for each stackSizeClass are implementation and CPU dependent.

Enumerator
epicsThreadStackSmall 
epicsThreadStackMedium 
epicsThreadStackBig 

Definition at line 89 of file epicsThread.h.

Function Documentation

LIBCOM_API epicsThreadId epicsStdCall epicsThreadCreate ( const char *  name,
unsigned int  priority,
unsigned int  stackSize,
EPICSTHREADFUNC  funptr,
void *  parm 
)

Short-hand for epicsThreadCreateOpt() to create an un-joinable thread.

Definition at line 33 of file epicsThread.cpp.

36 {
38  opts.priority = priority;
39  opts.stackSize = stackSize;
40  opts.joinable = 0;
41 
42  return epicsThreadCreateOpt(name, funptr, parm, &opts);
43 }
unsigned int joinable
Definition: epicsThread.h:158
unsigned int stackSize
Definition: epicsThread.h:154
unsigned int priority
Definition: epicsThread.h:150
#define EPICS_THREAD_OPTS_INIT
Definition: epicsThread.h:167
LIBCOM_API epicsThreadId epicsThreadCreateOpt(const char *name, EPICSTHREADFUNC funptr, void *parm, const epicsThreadOpts *opts)
Allocate and start a new OS thread.
Definition: osdThread.c:529
LIBCOM_API epicsThreadId epicsThreadCreateOpt ( const char *  name,
EPICSTHREADFUNC  funptr,
void *  parm,
const epicsThreadOpts opts 
)

Allocate and start a new OS thread.

Parameters
nameA name describing this thread. Appears in various log and error message.
funptrThe thread main function.
parmPassed to thread main function.
optsModifiers for the new thread, or NULL to use target specific defaults.
Returns
NULL on error

Definition at line 529 of file osdThread.c.

531 {
532  unsigned int stackSize;
533  epicsThreadOSD *pthreadInfo;
534  int status;
535  sigset_t blockAllSig, oldSig;
536 
537  epicsThreadInit();
538  assert(pcommonAttr);
539 
540  if (!opts) {
541  static const epicsThreadOpts opts_default = EPICS_THREAD_OPTS_INIT;
542  opts = &opts_default;
543  }
544  stackSize = opts->stackSize;
545  if (stackSize <= epicsThreadStackBig)
546  stackSize = epicsThreadGetStackSize(stackSize);
547 
548  sigfillset(&blockAllSig);
549  pthread_sigmask(SIG_SETMASK, &blockAllSig, &oldSig);
550 
551  pthreadInfo = init_threadInfo(name, opts->priority, stackSize, funptr,
552  parm, opts->joinable);
553  if (pthreadInfo==0)
554  return 0;
555 
556  pthreadInfo->isEpicsThread = 1;
557  setSchedulingPolicy(pthreadInfo, SCHED_FIFO);
558  pthreadInfo->isRealTimeScheduled = 1;
559 
560  if (pthreadInfo->joinable) {
561  /* extra ref for epicsThreadMustJoin() */
562  epicsAtomicIncrIntT(&pthreadInfo->refcnt);
563  }
564 
565  status = pthread_create(&pthreadInfo->tid, &pthreadInfo->attr,
566  start_routine, pthreadInfo);
567  if (status==EPERM) {
568  /* Try again without SCHED_FIFO*/
569  free_threadInfo(pthreadInfo);
570 
571  pthreadInfo = init_threadInfo(name, opts->priority, stackSize,
572  funptr, parm, opts->joinable);
573  if (pthreadInfo==0)
574  return 0;
575 
576  pthreadInfo->isEpicsThread = 1;
577  status = pthread_create(&pthreadInfo->tid, &pthreadInfo->attr,
578  start_routine, pthreadInfo);
579  }
580  checkStatusOnce(status, "pthread_create");
581  if (status) {
582  if (pthreadInfo->joinable) {
583  /* release extra ref which would have been for epicsThreadMustJoin() */
584  epicsAtomicDecrIntT(&pthreadInfo->refcnt);
585  }
586 
587  free_threadInfo(pthreadInfo);
588  return 0;
589  }
590 
591  status = pthread_sigmask(SIG_SETMASK, &oldSig, NULL);
592  checkStatusOnce(status, "pthread_sigmask");
593  return pthreadInfo;
594 }
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass stackSizeClass)
Definition: osdThread.c:466
pthread_t tid
Definition: osdThread.h:26
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
#define NULL
Definition: catime.c:38
unsigned int joinable
Definition: epicsThread.h:158
int isRealTimeScheduled
Definition: osdThread.h:36
int isEpicsThread
Definition: osdThread.h:35
unsigned int stackSize
Definition: epicsThread.h:154
EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT(int *pTarget)
pthread_attr_t attr
Definition: osdThread.h:28
unsigned int priority
Definition: epicsThread.h:150
#define checkStatusOnce(status, message)
Definition: osdThread.c:102
#define EPICS_THREAD_OPTS_INIT
Definition: epicsThread.h:167
EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT(int *pTarget)
LIBCOM_API void epicsStdCall epicsThreadExitMain ( void  )

If the main routine is done but wants to let other threads run it can call this routine. This should be the last call in main, except the final return. On most systems epicsThreadExitMain never returns.This must only be called by the main thread.

Definition at line 683 of file osdThread.c.

684 {
685  epicsThreadOSD *pthreadInfo;
686 
687  epicsThreadInit();
688  pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
689  if(pthreadInfo==NULL)
690  pthreadInfo = createImplicit();
691  if(pthreadInfo->createFunc) {
692  errlogPrintf("called from non-main thread\n");
693  cantProceed("epicsThreadExitMain");
694  }
695  else {
696  free_threadInfo(pthreadInfo);
697  pthread_exit(0);
698  }
699 }
#define NULL
Definition: catime.c:38
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
EPICSTHREADFUNC createFunc
Definition: osdThread.h:31
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
LIBCOM_API int epicsThreadGetCPUs ( void  )

Return a value approximating the number of threads which this target can run in parallel. This value is advisory.

Returns
>=1

Definition at line 990 of file osdThread.c.

991 {
992  long ret;
993 #ifdef _SC_NPROCESSORS_ONLN
994  ret = sysconf(_SC_NPROCESSORS_ONLN);
995  if (ret > 0)
996  return ret;
997 #endif
998 #ifdef _SC_NPROCESSORS_CONF
999  ret = sysconf(_SC_NPROCESSORS_CONF);
1000  if (ret > 0)
1001  return ret;
1002 #endif
1003  return 1;
1004 }
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetId ( const char *  name)

Attempt to find the first instance of a thread by name.

Returns
An epicsThreadId, or NULL if no such thread is currently running. Note that a non-NULL ID may still be invalid if this call races with thread exit.
Warning
Safe use of this function requires external knowledge that this thread will not return.

Definition at line 826 of file osdThread.c.

826  {
827  epicsThreadOSD *pthreadInfo;
828  int status;
829 
830  assert(epicsThreadOnceCalled);
831  status = mutexLock(&listLock);
832  checkStatus(status,"pthread_mutex_lock epicsThreadGetId");
833  if(status)
834  return NULL;
835  pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
836  while(pthreadInfo) {
837  if(strcmp(name,pthreadInfo->name) == 0) break;
838  pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
839  }
840  status = pthread_mutex_unlock(&listLock);
841  checkStatus(status,"pthread_mutex_unlock epicsThreadGetId");
842 
843  return(pthreadInfo);
844 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
ELLNODE node
Definition: osdThread.h:24
#define NULL
Definition: catime.c:38
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
#define checkStatus(status, message)
Definition: osdThread.c:87
char name[1]
Definition: osdThread.h:40
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf ( void  )

Find an epicsThreadId associated with the current thread. For non-EPICS threads, a new epicsThreadId may be allocated.

Definition at line 810 of file osdThread.c.

810  {
811  epicsThreadOSD *pthreadInfo;
812 
813  epicsThreadInit();
814  pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
815  if(pthreadInfo==NULL)
816  pthreadInfo = createImplicit();
817  assert ( pthreadInfo );
818  return(pthreadInfo);
819 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define NULL
Definition: catime.c:38
LIBCOM_API void epicsStdCall epicsThreadGetName ( epicsThreadId  id,
char *  name,
size_t  size 
)

Copy out the thread name into the provided buffer.

Guaranteed to be null terminated. size is number of bytes in buffer to hold name (including terminator). Failure results in an empty string stored in name.

Definition at line 857 of file osdThread.c.

858 {
859  assert(epicsThreadOnceCalled);
860  strncpy(name, pthreadInfo->name, size-1);
861  name[size-1] = '\0';
862 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API const char* epicsStdCall epicsThreadGetNameSelf ( void  )

Return the name of the current thread.

Returns
Never NULL. Storage lifetime tied to epicsThreadId.

This is either a copy of the string passed to epicsThread*Create*(), or an arbitrary unique string for non-EPICS threads.

Definition at line 846 of file osdThread.c.

847 {
848  epicsThreadOSD *pthreadInfo;
849 
850  epicsThreadInit();
851  pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
852  if(pthreadInfo==NULL)
853  pthreadInfo = createImplicit();
854  return(pthreadInfo->name);
855 }
#define NULL
Definition: catime.c:38
char name[1]
Definition: osdThread.h:40
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPriority ( epicsThreadId  id)

Return thread OSI priority

Definition at line 701 of file osdThread.c.

702 {
703  assert(epicsThreadOnceCalled);
704  return(pthreadInfo->osiPriority);
705 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPrioritySelf ( void  )

Return thread OSI priority

Definition at line 707 of file osdThread.c.

708 {
709  epicsThreadInit();
711 }
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPriority(epicsThreadId pthreadInfo)
Definition: osdThread.c:701
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize ( epicsThreadStackSizeClass  size)

Get a stack size value that can be given to epicsThreadCreate().

Parameters
sizeone of the values epicsThreadStackSmall, epicsThreadStackMedium or epicsThreadStackBig.

Definition at line 466 of file osdThread.c.

467 {
468 #if defined (OSITHREAD_USE_DEFAULT_STACK)
469  return 0;
470 #elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0
471  if (stackSizeClass<epicsThreadStackSmall) {
472  errlogPrintf("epicsThreadGetStackSize illegal argument (too small)");
473  return stackSizeTable[epicsThreadStackBig];
474  }
475 
476  if (stackSizeClass>epicsThreadStackBig) {
477  errlogPrintf("epicsThreadGetStackSize illegal argument (too large)");
478  return stackSizeTable[epicsThreadStackBig];
479  }
480 
481  return stackSizeTable[stackSizeClass];
482 #else
483  return 0;
484 #endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
485 }
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadHighestPriorityLevelBelow ( unsigned int  priority,
unsigned *  pPriorityJustBelow 
)

Lookup the next usage OSI priority such that priority > *pPriorityJustBelow if this is possible with the current target configuration and privlages.

Definition at line 740 of file osdThread.c.

742 {
743  unsigned newPriority = priority - 1;
744 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
745  int diff;
746  diff = pcommonAttr->maxPriority - pcommonAttr->minPriority;
747  if(diff<0) diff = -diff;
748  if(diff>1 && diff <100) newPriority -= 100/(diff+1);
749 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
750  if (newPriority <= 99) {
751  *pPriorityJustBelow = newPriority;
753  }
755 }
int maxPriority
Definition: osdThread.c:64
int minPriority
Definition: osdThread.c:65
LIBCOM_API int epicsThreadHookAdd ( EPICS_THREAD_HOOK_ROUTINE  hook)

Register a routine to be called by every new thread before the thread function gets run. Hook routines will often register a thread exit routine with epicsAtThreadExit() to release thread-specific resources they have allocated.

Definition at line 54 of file osdThreadHooks.c.

55 {
56  epicsThreadHook *pHook;
57 
58  if (!hook) return 0;
59  threadHookInit();
60 
61  pHook = calloc(1, sizeof(epicsThreadHook));
62  if (!pHook) {
63  fprintf(stderr, "epicsThreadHookAdd: calloc failed\n");
64  return -1;
65  }
66  pHook->func = hook;
67 
68  if (epicsMutexLock(hookLock) == epicsMutexLockOK) {
69  ellAdd(&hookList, &pHook->node);
70  epicsMutexUnlock(hookLock);
71  return 0;
72  }
73  fprintf(stderr, "epicsThreadHookAdd: Locking problem\n");
74  return -1;
75 }
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
epicsMutexLockStatus epicsStdCall epicsMutexLock(epicsMutexId pmutexNode)
Claim the semaphore, waiting until it&#39;s free if currently owned owned by a different thread...
Definition: epicsMutex.cpp:145
#define stderr
Definition: epicsStdio.h:32
EPICS_THREAD_HOOK_ROUTINE func
LIBCOM_API int epicsThreadHookDelete ( EPICS_THREAD_HOOK_ROUTINE  hook)

Remove routine from the list of hooks run at thread creation time.

Definition at line 77 of file osdThreadHooks.c.

78 {
79  if (!hook) return 0;
80  threadHookInit();
81 
82  if (epicsMutexLock(hookLock) == epicsMutexLockOK) {
83  epicsThreadHook *pHook = (epicsThreadHook *) ellFirst(&hookList);
84 
85  while (pHook) {
86  if (hook == pHook->func) {
87  ellDelete(&hookList, &pHook->node);
88  break;
89  }
90  pHook = (epicsThreadHook *) ellNext(&pHook->node);
91  }
92  epicsMutexUnlock(hookLock);
93  return 0;
94  }
95  fprintf(stderr, "epicsThreadHookAdd: Locking problem\n");
96  return -1;
97 }
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
epicsMutexLockStatus epicsStdCall epicsMutexLock(epicsMutexId pmutexNode)
Claim the semaphore, waiting until it&#39;s free if currently owned owned by a different thread...
Definition: epicsMutex.cpp:145
#define stderr
Definition: epicsStdio.h:32
EPICS_THREAD_HOOK_ROUTINE func
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
LIBCOM_API void epicsThreadHooksShow ( void  )

Print the current list of hook function pointers.

Definition at line 123 of file osdThreadHooks.c.

124 {
125  threadHookInit();
126 
127  if (epicsMutexLock(hookLock) == epicsMutexLockOK) {
128  epicsThreadHook *pHook = (epicsThreadHook *) ellFirst(&hookList);
129 
130  while (pHook) {
131  printf(" %p\n", pHook->func);
132  pHook = (epicsThreadHook *) ellNext(&pHook->node);
133  }
134  epicsMutexUnlock(hookLock);
135  }
136  else {
137  fprintf(stderr, "epicsThreadHooksShow: Locking problem\n");
138  }
139 }
#define printf
Definition: epicsStdio.h:41
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
epicsMutexLockStatus epicsStdCall epicsMutexLock(epicsMutexId pmutexNode)
Claim the semaphore, waiting until it&#39;s free if currently owned owned by a different thread...
Definition: epicsMutex.cpp:145
#define stderr
Definition: epicsStdio.h:32
EPICS_THREAD_HOOK_ROUTINE func
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
LIBCOM_API int epicsStdCall epicsThreadIsEqual ( epicsThreadId  id1,
epicsThreadId  id2 
)

Test if two thread IDs actually refer to the same OS thread

Definition at line 776 of file osdThread.c.

777 {
778  assert(epicsThreadOnceCalled);
779  assert(p1);
780  assert(p2);
781  return(pthread_equal(p1->tid,p2->tid));
782 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API int epicsStdCall epicsThreadIsOkToBlock ( void  )

Is it OK for a thread to block? This can be called by support code that does not know if it is called in a thread that should not block. For example the errlog system calls this to decide when messages should be displayed on the console.

Definition at line 358 of file epicsThread.cpp.

359  {
360  const int *pokToBlock;
361  epicsThreadOnce(&okToBlockOnce, epicsThreadOnceIdInit, NULL);
362  pokToBlock = (int *) epicsThreadPrivateGet(okToBlockPrivate);
363  return (pokToBlock ? *pokToBlock : 0);
364  }
epicsThreadPrivateId okToBlockPrivate
LIBCOM_API void *epicsStdCall epicsThreadPrivateGet(epicsThreadPrivateId)
Definition: osdThread.c:973
#define NULL
Definition: catime.c:38
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
LIBCOM_API int epicsStdCall epicsThreadIsSuspended ( epicsThreadId  id)

How and why a thread can be suspended is implementation dependent. A thread calling epicsThreadSuspendSelf() should result in this routine returning true for that thread, but a thread may also be suspended for other reasons.

Definition at line 784 of file osdThread.c.

784  {
785  assert(epicsThreadOnceCalled);
786  assert(pthreadInfo);
787  return(pthreadInfo->isSuspended ? 1 : 0);
788 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadLowestPriorityLevelAbove ( unsigned int  priority,
unsigned *  pPriorityJustAbove 
)

Lookup the next usage OSI priority such that priority < *pPriorityJustBelow if this is possible with the current target configuration and privlages.

Definition at line 757 of file osdThread.c.

759 {
760  unsigned newPriority = priority + 1;
761 
762 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
763  int diff;
764  diff = pcommonAttr->maxPriority - pcommonAttr->minPriority;
765  if(diff<0) diff = -diff;
766  if(diff>1 && diff <100) newPriority += 100/(diff+1);
767 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
768 
769  if (newPriority <= 99) {
770  *pPriorityJustAbove = newPriority;
772  }
774 }
int maxPriority
Definition: osdThread.c:64
int minPriority
Definition: osdThread.c:65
LIBCOM_API void epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE  func)

Call func once for every known thread.

Definition at line 864 of file osdThread.c.

865 {
866  epicsThreadOSD *pthreadInfo;
867  int status;
868 
869  epicsThreadInit();
870  status = mutexLock(&listLock);
871  checkStatus(status, "pthread_mutex_lock epicsThreadMap");
872  if (status)
873  return;
874  pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
875  while (pthreadInfo) {
876  func(pthreadInfo);
877  pthreadInfo = (epicsThreadOSD *)ellNext(&pthreadInfo->node);
878  }
879  status = pthread_mutex_unlock(&listLock);
880  checkStatus(status, "pthread_mutex_unlock epicsThreadMap");
881 }
pvd::Status status
ELLNODE node
Definition: osdThread.h:24
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
#define checkStatus(status, message)
Definition: osdThread.c:87
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
LIBCOM_API epicsThreadId epicsStdCall epicsThreadMustCreate ( const char *  name,
unsigned int  priority,
unsigned int  stackSize,
EPICSTHREADFUNC  funptr,
void *  parm 
)

Short-hand for epicsThreadCreateOpt() to create an un-joinable thread. On error calls cantProceed()

Definition at line 374 of file epicsThread.cpp.

377  {
379  name, priority, stackSize, funptr, parm );
380  assert ( id );
381  return id;
382  }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
epicsThreadId epicsStdCall epicsThreadCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
Definition: epicsThread.cpp:33
LIBCOM_API void epicsThreadMustJoin ( epicsThreadId  id)

Wait for a joinable thread to exit (return from its main function)

Definition at line 632 of file osdThread.c.

633 {
634  void *ret = NULL;
635  int status;
636 
637  if(!id) {
638  return;
639  } else if(epicsAtomicCmpAndSwapIntT(&id->joinable, 1, 0)!=1) {
640  if(epicsThreadGetIdSelf()==id) {
641  errlogPrintf("Warning: %s thread self-join of unjoinable\n", id->name);
642 
643  } else {
644  /* try to error nicely, however in all likelyhood de-ref of
645  * 'id' has already caused SIGSEGV as we are racing thread exit,
646  * which free's 'id'.
647  */
648  cantProceed("Error: %s thread not joinable.\n", id->name);
649  }
650  return;
651  }
652 
653  status = pthread_join(id->tid, &ret);
654  if(status == EDEADLK) {
655  /* Thread can't join itself (directly or indirectly)
656  * so we detach instead.
657  */
658  status = pthread_detach(id->tid);
659  checkStatusOnce(status, "pthread_detach");
660  } else checkStatusOnce(status, "pthread_join");
661  free_threadInfo(id);
662 }
pthread_t tid
Definition: osdThread.h:26
pvd::Status status
#define NULL
Definition: catime.c:38
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT(int *pTarget, int oldVal, int newVal)
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
char name[1]
Definition: osdThread.h:40
#define checkStatusOnce(status, message)
Definition: osdThread.c:102
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810
LIBCOM_API void epicsStdCall epicsThreadOnce ( epicsThreadOnceId id,
EPICSTHREADFUNC  ,
void *  arg 
)

Perform one-time initialization.

Run the provided function if it has not run, and is not running in some other thread.

For each unique epicsThreadOnceId, epicsThreadOnce guarantees that

  1. myInitFunc will only be called only once.
  2. myInitFunc will have returned before any other epicsThreadOnce call using the same epicsThreadOnceId returns.
1 static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
2 static void myInitFunc(void *arg) { ... }
3 static void some Function(void) {
4  epicsThreadOnce(&onceId, &myInitFunc, NULL);
5 }
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate ( void  )

Allocate a new thread local variable. This variable will initially hold NULL for each thread.

Definition at line 934 of file osdThread.c.

935 {
936  pthread_key_t *key;
937  int status;
938 
939  epicsThreadInit();
940  key = calloc(1,sizeof(pthread_key_t));
941  if(!key)
942  return NULL;
943  status = pthread_key_create(key,0);
944  checkStatus(status,"pthread_key_create epicsThreadPrivateCreate");
945  if(status)
946  return NULL;
947  return((epicsThreadPrivateId)key);
948 }
pvd::Status status
#define NULL
Definition: catime.c:38
#define checkStatus(status, message)
Definition: osdThread.c:87
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete ( epicsThreadPrivateId  id)

Free a thread local variable

Definition at line 950 of file osdThread.c.

951 {
952  pthread_key_t *key = (pthread_key_t *)id;
953  int status;
954 
955  assert(epicsThreadOnceCalled);
956  status = pthread_key_delete(*key);
957  checkStatusQuit(status,"pthread_key_delete","epicsThreadPrivateDelete");
958  free((void *)key);
959 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
#define checkStatusQuit(status, message, method)
Definition: osdThread.c:92
LIBCOM_API void* epicsStdCall epicsThreadPrivateGet ( epicsThreadPrivateId  )

Fetch the current value of a thread local variable

Definition at line 973 of file osdThread.c.

974 {
975  pthread_key_t *key = (pthread_key_t *)id;
976 
977  assert(epicsThreadOnceCalled);
978  return pthread_getspecific(*key);
979 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API void epicsStdCall epicsThreadPrivateSet ( epicsThreadPrivateId  ,
void *   
)

Update thread local variable

Definition at line 961 of file osdThread.c.

962 {
963  pthread_key_t *key = (pthread_key_t *)id;
964  int status;
965 
966  assert(epicsThreadOnceCalled);
967  if(errVerbose && !value)
968  errlogPrintf("epicsThreadPrivateSet: setting value of 0\n");
969  status = pthread_setspecific(*key,value);
970  checkStatusQuit(status,"pthread_setspecific","epicsThreadPrivateSet");
971 }
Definition: link.h:174
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
int errVerbose
Definition: errlog.c:41
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
#define checkStatusQuit(status, message, method)
Definition: osdThread.c:92
LIBCOM_API void epicsThreadRealtimeLock ( void  )

When real-time scheduling is active, attempt any post-init operations that preserve real-time performance. For POSIX targets this locks the process into RAM, preventing swap-related VM faults.

Definition at line 425 of file osdThread.c.

426 {
427 #if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0
428  if (pcommonAttr->maxPriority > pcommonAttr->minPriority) {
429  int status = mlockall(MCL_CURRENT | MCL_FUTURE);
430 
431  if (status) {
432  const int err = errno;
433  switch(err) {
434 #ifdef __linux__
435  case ENOMEM:
436  fprintf(stderr, "epicsThreadRealtimeLock "
437  "Warning: unable to lock memory. RLIMIT_MEMLOCK is too small or missing CAP_IPC_LOCK\n");
438  break;
439  case EPERM:
440  fprintf(stderr, "epicsThreadRealtimeLock "
441  "Warning: unable to lock memory. missing CAP_IPC_LOCK\n");
442  break;
443 #endif
444  default:
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",
448  err);
449  }
450  }
451  }
452 #endif
453 }
pvd::Status status
int maxPriority
Definition: osdThread.c:64
int minPriority
Definition: osdThread.c:65
#define stderr
Definition: epicsStdio.h:32
LIBCOM_API void epicsStdCall epicsThreadResume ( epicsThreadId  id)

Resume a thread suspended with epicsThreadSuspendSelf()

Definition at line 423 of file osdThread.c.

424 {
425  rtems_id tid = (rtems_id)id;
426  rtems_status_code sc;
427 
428  sc = rtems_task_resume (tid);
429  if (sc != RTEMS_SUCCESSFUL)
430  errlogPrintf("epicsThreadResume failed: %s\n",
431  rtems_status_text (sc));
432 }
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
LIBCOM_API void epicsStdCall epicsThreadSetOkToBlock ( int  isOkToBlock)

When a thread is started the default is that it is not allowed to block. This method can be called to change the state. For example iocsh calls this to specify that it is OK to block.

Definition at line 366 of file epicsThread.cpp.

367  {
368  const int *pokToBlock;
369  epicsThreadOnce(&okToBlockOnce, epicsThreadOnceIdInit, NULL);
370  pokToBlock = (isOkToBlock) ? &okToBlockYes : &okToBlockNo;
371  epicsThreadPrivateSet(okToBlockPrivate, (void *)pokToBlock);
372  }
epicsThreadPrivateId okToBlockPrivate
#define NULL
Definition: catime.c:38
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
LIBCOM_API void epicsStdCall epicsThreadPrivateSet(epicsThreadPrivateId, void *)
Definition: osdThread.c:961
LIBCOM_API void epicsStdCall epicsThreadSetPriority ( epicsThreadId  id,
unsigned int  priority 
)

Change OSI priority of target thread.

Definition at line 713 of file osdThread.c.

714 {
715 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
716  int status;
717 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
718 
719  assert(epicsThreadOnceCalled);
720  assert(pthreadInfo);
721  if(!pthreadInfo->isEpicsThread) {
722  fprintf(stderr,"epicsThreadSetPriority called by non epics thread\n");
723  return;
724  }
725  pthreadInfo->osiPriority = priority;
726  if(!pthreadInfo->isRealTimeScheduled) return;
727 
728 #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
729  if(!pcommonAttr->usePolicy) return;
730  pthreadInfo->schedParam.sched_priority = epicsThreadGetPosixPriority(pthreadInfo);
731  status = pthread_attr_setschedparam(
732  &pthreadInfo->attr,&pthreadInfo->schedParam);
733  if(errVerbose) checkStatus(status,"pthread_attr_setschedparam");
734  status = pthread_setschedparam(
735  pthreadInfo->tid, pthreadInfo->schedPolicy, &pthreadInfo->schedParam);
736  if(errVerbose) checkStatus(status,"pthread_setschedparam");
737 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
738 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
int usePolicy
Definition: osdThread.c:67
LIBCOM_API int epicsThreadGetPosixPriority(epicsThreadId pthreadInfo)
Definition: osdThread.c:115
int errVerbose
Definition: errlog.c:41
#define checkStatus(status, message)
Definition: osdThread.c:87
#define stderr
Definition: epicsStdio.h:32
LIBCOM_API void epicsStdCall epicsThreadShow ( epicsThreadId  id,
unsigned int  level 
)

Print info about a single EPICS thread.

Definition at line 903 of file osdThread.c.

904 {
905  epicsThreadOSD *pthreadInfo;
906  int status;
907  int found = 0;
908 
909  epicsThreadInit();
910  if(!showThread) {
911  epicsThreadShowInfo(0,level);
912  return;
913  }
914  status = mutexLock(&listLock);
915  checkStatus(status,"pthread_mutex_lock epicsThreadShowAll");
916  if(status)
917  return;
918  pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
919  while(pthreadInfo) {
920  if (((epicsThreadId)pthreadInfo == showThread)
921  || ((epicsThreadId)pthreadInfo->tid == showThread)) {
922  found = 1;
923  epicsThreadShowInfo(pthreadInfo,level);
924  }
925  pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
926  }
927  status = pthread_mutex_unlock(&listLock);
928  checkStatus(status,"pthread_mutex_unlock epicsThreadShowAll");
929  if(status) return;
930  if (!found)
931  printf("Thread %#lx (%lu) not found.\n", (unsigned long)showThread, (unsigned long)showThread);
932 }
pthread_t tid
Definition: osdThread.h:26
pvd::Status status
ELLNODE node
Definition: osdThread.h:24
#define printf
Definition: epicsStdio.h:41
struct epicsThreadOSD * epicsThreadId
Definition: epicsThread.h:106
LIBCOM_API void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
#define checkStatus(status, message)
Definition: osdThread.c:87
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
LIBCOM_API void epicsStdCall epicsThreadShowAll ( unsigned int  level)

Print to stdout information about all running EPICS threads.

Parameters
level0 prints minimal output. Higher values print more details.

Definition at line 883 of file osdThread.c.

884 {
885  epicsThreadOSD *pthreadInfo;
886  int status;
887 
888  epicsThreadInit();
889  epicsThreadShow(0,level);
890  status = mutexLock(&listLock);
891  checkStatus(status,"pthread_mutex_lock epicsThreadShowAll");
892  if(status)
893  return;
894  pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
895  while(pthreadInfo) {
896  epicsThreadShowInfo(pthreadInfo,level);
897  pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
898  }
899  status = pthread_mutex_unlock(&listLock);
900  checkStatus(status,"pthread_mutex_unlock epicsThreadShowAll");
901 }
pvd::Status status
ELLNODE node
Definition: osdThread.h:24
LIBCOM_API void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
#define checkStatus(status, message)
Definition: osdThread.c:87
LIBCOM_API void epicsStdCall epicsThreadShow(epicsThreadId showThread, unsigned int level)
Definition: osdThread.c:903
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
LIBCOM_API void epicsStdCall epicsThreadSleep ( double  seconds)

Block the calling thread for at least the specified time.

Parameters
secondsTime to wait in seconds. Values <=0 blocks for the shortest possible time.

Definition at line 790 of file osdThread.c.

791 {
792  struct timespec delayTime;
793  struct timespec remainingTime;
794  double nanoseconds;
795 
796  if (seconds > 0) {
797  delayTime.tv_sec = seconds;
798  nanoseconds = (seconds - delayTime.tv_sec) *1e9;
799  delayTime.tv_nsec = nanoseconds;
800  }
801  else {
802  delayTime.tv_sec = 0;
803  delayTime.tv_nsec = 0;
804  }
805  while (nanosleep(&delayTime, &remainingTime) == -1 &&
806  errno == EINTR)
807  delayTime = remainingTime;
808 }
time_t tv_sec
Definition: osdTime.h:22
Defined by POSIX Real Time.
Definition: osdTime.h:21
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum ( void  )

Query a value approximating the OS timer/scheduler resolution.

Returns
A value in seconds >=0
Warning
On targets other than vxWorks and RTEMS, the quantum value often isn't meaningful. Use of this function is discouraged in portable code.

Definition at line 981 of file osdThread.c.

982 {
983  double hz;
984  hz = sysconf ( _SC_CLK_TCK );
985  if(hz<=0)
986  return 0.0;
987  return 1.0 / hz;
988 }
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf ( void  )

Block the current thread until epicsThreadResume().

Definition at line 664 of file osdThread.c.

665 {
666  epicsThreadOSD *pthreadInfo;
667 
668  epicsThreadInit();
669  pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
670  if(pthreadInfo==NULL)
671  pthreadInfo = createImplicit();
672  pthreadInfo->isSuspended = 1;
673  epicsEventWait(pthreadInfo->suspendEvent);
674 }
epicsEventId suspendEvent
Definition: osdThread.h:33
#define epicsEventWait(ID)
Definition: osdEvent.h:19
#define NULL
Definition: catime.c:38