This is Unofficial EPICS BASE Doxygen Site
osdThread.c File Reference
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#include "epicsStdio.h"
#include "ellLib.h"
#include "epicsEvent.h"
#include "epicsMutex.h"
#include "epicsString.h"
#include "epicsThread.h"
#include "cantProceed.h"
#include "errlog.h"
#include "epicsAssert.h"
#include "epicsExit.h"
#include "epicsAtomic.h"
+ Include dependency graph for osdThread.c:

Go to the source code of this file.

Classes

struct  commonAttr
 

Macros

#define checkStatus(status, message)
 
#define checkStatusQuit(status, message, method)
 
#define checkStatusOnce(status, message)
 
#define checkStatusOnceQuit(status, message, method)
 
#define STACK_SIZE(f)   (0)
 
#define EPICS_THREAD_ONCE_DONE   &threadOnceComplete
 

Typedefs

typedef struct commonAttr commonAttr
 

Functions

LIBCOM_API void epicsThreadShowInfo (epicsThreadOSD *pthreadInfo, unsigned int level)
 
LIBCOM_API void osdThreadHooksRun (epicsThreadId id)
 
LIBCOM_API void osdThreadHooksRunMain (epicsThreadId id)
 
LIBCOM_API int epicsThreadGetPosixPriority (epicsThreadId pthreadInfo)
 
LIBCOM_API void epicsThreadRealtimeLock (void)
 
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
 
LIBCOM_API void epicsStdCall epicsThreadOnce (epicsThreadOnceId *id, void(*func)(void *), void *arg)
 
epicsThreadId epicsThreadCreateOpt (const char *name, EPICSTHREADFUNC funptr, void *parm, const epicsThreadOpts *opts)
 Allocate and start a new OS thread. More...
 
void epicsThreadMustJoin (epicsThreadId id)
 
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf (void)
 
LIBCOM_API void epicsStdCall epicsThreadResume (epicsThreadOSD *pthreadInfo)
 
LIBCOM_API void epicsStdCall epicsThreadExitMain (void)
 
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPriority (epicsThreadId pthreadInfo)
 
LIBCOM_API unsigned int epicsStdCall epicsThreadGetPrioritySelf (void)
 
LIBCOM_API void epicsStdCall epicsThreadSetPriority (epicsThreadId pthreadInfo, 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 p1, epicsThreadId p2)
 
LIBCOM_API int epicsStdCall epicsThreadIsSuspended (epicsThreadId pthreadInfo)
 
LIBCOM_API void epicsStdCall epicsThreadSleep (double seconds)
 Block the calling thread for at least the specified time. More...
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf (void)
 
LIBCOM_API pthread_t epicsThreadGetPosixThreadId (epicsThreadId threadId)
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetId (const char *name)
 
LIBCOM_API const char epicsStdCall * epicsThreadGetNameSelf ()
 
LIBCOM_API void epicsStdCall epicsThreadGetName (epicsThreadId pthreadInfo, char *name, size_t size)
 
LIBCOM_API void epicsThreadMap (EPICS_THREAD_HOOK_ROUTINE func)
 
LIBCOM_API void epicsStdCall epicsThreadShowAll (unsigned int level)
 
LIBCOM_API void epicsStdCall epicsThreadShow (epicsThreadId showThread, unsigned int level)
 
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate (void)
 
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete (epicsThreadPrivateId id)
 
LIBCOM_API void epicsStdCall epicsThreadPrivateSet (epicsThreadPrivateId id, void *value)
 
LIBCOM_API void epicsStdCall * epicsThreadPrivateGet (epicsThreadPrivateId id)
 
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum ()
 Query a value approximating the OS timer/scheduler resolution. More...
 
LIBCOM_API int epicsThreadGetCPUs (void)
 

Macro Definition Documentation

#define checkStatus (   status,
  message 
)
Value:
if((status)) {\
errlogPrintf("%s error %s\n",(message),strerror((status))); \
}
pvd::Status status
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105

Definition at line 87 of file osdThread.c.

#define checkStatusOnce (   status,
  message 
)
Value:
if((status)) {\
fprintf(stderr,"%s error %s\n",(message),strerror((status))); }
pvd::Status status
#define stderr
Definition: epicsStdio.h:32

Definition at line 102 of file osdThread.c.

#define checkStatusOnceQuit (   status,
  message,
  method 
)
Value:
if(status) { \
fprintf(stderr,"%s error %s",(message),strerror((status))); \
fprintf(stderr," %s\n",method); \
fprintf(stderr,"epicsThreadInit cant proceed. Program exiting\n"); \
exit(-1);\
}
pvd::Status status
#define stderr
Definition: epicsStdio.h:32

Definition at line 106 of file osdThread.c.

#define checkStatusQuit (   status,
  message,
  method 
)
Value:
if(status) { \
errlogPrintf("%s error %s\n",(message),strerror((status))); \
cantProceed((method)); \
}
pvd::Status status
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54

Definition at line 92 of file osdThread.c.

#define EPICS_THREAD_ONCE_DONE   &threadOnceComplete
#define STACK_SIZE (   f)    (0)

Definition at line 463 of file osdThread.c.

Typedef Documentation

typedef struct commonAttr commonAttr

Function Documentation

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
char name[1]
Definition: osdThread.h:40
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 int epicsThreadGetPosixPriority ( epicsThreadId  pthreadInfo)

Definition at line 115 of file osdThread.c.

116 {
117 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
118  double maxPriority,minPriority,slope,oss;
119 
120  if(pcommonAttr->maxPriority==pcommonAttr->minPriority)
121  return(pcommonAttr->maxPriority);
122  maxPriority = (double)pcommonAttr->maxPriority;
123  minPriority = (double)pcommonAttr->minPriority;
124  slope = (maxPriority - minPriority)/100.0;
125  oss = (double)pthreadInfo->osiPriority * slope + minPriority;
126  return((int)oss);
127 #else
128  return 0;
129 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
130 }
unsigned int osiPriority
Definition: osdThread.h:38
int maxPriority
Definition: osdThread.c:64
int minPriority
Definition: osdThread.c:65
LIBCOM_API pthread_t epicsThreadGetPosixThreadId ( epicsThreadId  threadId)

Definition at line 821 of file osdThread.c.

822 {
823  return threadId->tid;
824 }
pthread_t tid
Definition: osdThread.h:26
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
unsigned int osiPriority
Definition: osdThread.h:38
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 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 }
pthread_t tid
Definition: osdThread.h:26
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
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
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,
void(*)(void *)  func,
void *  arg 
)

Definition at line 487 of file osdThread.c.

488 {
489  static struct epicsThreadOSD threadOnceComplete;
490  #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
491  int status;
492 
493  epicsThreadInit();
494  status = mutexLock(&onceLock);
495  if(status) {
496  fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
497  strerror(status));
498  exit(-1);
499  }
500 
501  if (*id != EPICS_THREAD_ONCE_DONE) {
502  if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
503  *id = epicsThreadGetIdSelf(); /* mark active */
504  status = pthread_mutex_unlock(&onceLock);
505  checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
506  func(arg);
507  status = mutexLock(&onceLock);
508  checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
509  *id = EPICS_THREAD_ONCE_DONE; /* mark done */
510  } else if (*id == epicsThreadGetIdSelf()) {
511  status = pthread_mutex_unlock(&onceLock);
512  checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
513  cantProceed("Recursive epicsThreadOnce() initialization\n");
514  } else
515  while (*id != EPICS_THREAD_ONCE_DONE) {
516  /* Another thread is in the above func(arg) call. */
517  status = pthread_mutex_unlock(&onceLock);
518  checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
520  status = mutexLock(&onceLock);
521  checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
522  }
523  }
524  status = pthread_mutex_unlock(&onceLock);
525  checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
526 }
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
pvd::Status status
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum()
Query a value approximating the OS timer/scheduler resolution.
Definition: osdThread.c:981
#define EPICS_THREAD_ONCE_INIT
Definition: epicsThread.h:109
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
#define stderr
Definition: epicsStdio.h:32
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810
#define checkStatusQuit(status, message, method)
Definition: osdThread.c:92
#define EPICS_THREAD_ONCE_DONE
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 ( epicsThreadOSD pthreadInfo)

Definition at line 676 of file osdThread.c.

677 {
678  assert(epicsThreadOnceCalled);
679  pthreadInfo->isSuspended = 0;
680  epicsEventSignal(pthreadInfo->suspendEvent);
681 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
epicsEventId suspendEvent
Definition: osdThread.h:33
#define epicsEventSignal(ID)
A synonym for epicsEventTrigger().
Definition: epicsEvent.h:172
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 }
pthread_t tid
Definition: osdThread.h:26
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
unsigned int osiPriority
Definition: osdThread.h:38
pvd::Status status
struct sched_param schedParam
Definition: osdThread.h:29
int isRealTimeScheduled
Definition: osdThread.h:36
int usePolicy
Definition: osdThread.c:67
int isEpicsThread
Definition: osdThread.h:35
LIBCOM_API int epicsThreadGetPosixPriority(epicsThreadId pthreadInfo)
Definition: osdThread.c:115
int errVerbose
Definition: errlog.c:41
#define checkStatus(status, message)
Definition: osdThread.c:87
pthread_attr_t attr
Definition: osdThread.h:28
#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 epicsThreadShowInfo ( epicsThreadOSD pthreadInfo,
unsigned int  level 
)

Definition at line 22 of file osdThreadExtra.c.

23 {
24  if(!pthreadInfo) {
25  fprintf(epicsGetStdout()," NAME EPICS ID "
26  "PTHREAD ID OSIPRI OSSPRI STATE\n");
27  } else {
28  struct sched_param param;
29  int policy;
30  int priority = 0;
31 
32  if(pthreadInfo->tid) {
33  int status;
34  status = pthread_getschedparam(pthreadInfo->tid,&policy,&param);
35  if(!status) priority = param.sched_priority;
36  }
37  fprintf(epicsGetStdout(),"%16.16s %14p %12lu %3d%8d %8.8s\n",
38  pthreadInfo->name,(void *)
39  pthreadInfo,(unsigned long)pthreadInfo->tid,
40  pthreadInfo->osiPriority,priority,
41  pthreadInfo->isSuspended?"SUSPEND":"OK");
42  }
43 }
pthread_t tid
Definition: osdThread.h:26
unsigned int osiPriority
Definition: osdThread.h:38
pvd::Status status
FILE *epicsStdCall epicsGetStdout(void)
Definition: epicsStdio.c:47
char name[1]
Definition: osdThread.h:40
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
LIBCOM_API void osdThreadHooksRun ( epicsThreadId  id)

Definition at line 105 of file osdThreadHooks.c.

106 {
107  threadHookInit();
108 
109  if (epicsMutexLock(hookLock) == epicsMutexLockOK) {
110  epicsThreadHook *pHook = (epicsThreadHook *) ellFirst(&hookList);
111 
112  while (pHook) {
113  pHook->func(id);
114  pHook = (epicsThreadHook *) ellNext(&pHook->node);
115  }
116  epicsMutexUnlock(hookLock);
117  }
118  else {
119  fprintf(stderr, "osdThreadHooksRun: Locking problem\n");
120  }
121 }
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 void osdThreadHooksRunMain ( epicsThreadId  id)

Definition at line 99 of file osdThreadHooks.c.

100 {
103 }
LIBCOM_API EPICS_THREAD_HOOK_ROUTINE epicsThreadHookMain