This is Unofficial EPICS BASE Doxygen Site
osdThread.c File Reference
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "epicsStdio.h"
#include "libComAPI.h"
#include "epicsThread.h"
#include "cantProceed.h"
#include "epicsAssert.h"
#include "ellLib.h"
#include "epicsExit.h"
#include "epicsAtomic.h"
+ Include dependency graph for osdThread.c:

Go to the source code of this file.

Classes

struct  win32ThreadGlobal
 
struct  epicsThreadOSD
 
struct  epicsThreadPrivateOSD
 

Macros

#define VC_EXTRALEAN
 
#define STRICT
 
#define _WIN32_WINNT   0x400 /* No support for W95 */
 
#define STACK_SIZE_PARAM_IS_A_RESERVATION   0x00010000
 
#define osdOrdinaryPriorityStateCount   5u
 
#define osdRealtimePriorityStateCount   14u
 
#define STACK_SIZE(f)   (f * 0x10000 * sizeof(void *))
 
#define EPICS_THREAD_ONCE_DONE   & threadOnceComplete
 

Typedefs

typedef struct win32ThreadGlobal win32ThreadGlobal
 
typedef struct epicsThreadOSD win32ThreadParam
 
typedef struct epicsThreadPrivateOSD epicsThreadPrivateOSD
 

Functions

LIBCOM_API void osdThreadHooksRun (epicsThreadId id)
 
void setThreadName (DWORD dwThreadID, LPCSTR szThreadName)
 
LIBCOM_API void epicsStdCall epicsThreadExitMain (void)
 
LIBCOM_API void epicsThreadRealtimeLock (void)
 
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadLowestPriorityLevelAbove (unsigned int priority, unsigned *pPriorityJustAbove)
 
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadHighestPriorityLevelBelow (unsigned int priority, unsigned *pPriorityJustBelow)
 
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
 
epicsThreadId epicsThreadCreateOpt (const char *pName, EPICSTHREADFUNC pFunc, void *pParm, const epicsThreadOpts *opts)
 Allocate and start a new OS thread. More...
 
void epicsThreadMustJoin (epicsThreadId id)
 
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf ()
 
LIBCOM_API void epicsStdCall epicsThreadResume (epicsThreadId id)
 
LIBCOM_API unsigned epicsStdCall epicsThreadGetPriority (epicsThreadId id)
 
LIBCOM_API unsigned epicsStdCall epicsThreadGetPrioritySelf ()
 
LIBCOM_API void epicsStdCall epicsThreadSetPriority (epicsThreadId id, unsigned priority)
 
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...
 
double epicsStdCall epicsThreadSleepQuantum ()
 Query a value approximating the OS timer/scheduler resolution. More...
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf (void)
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetId (const char *pName)
 
LIBCOM_API const char *epicsStdCall epicsThreadGetNameSelf (void)
 
LIBCOM_API void epicsStdCall epicsThreadGetName (epicsThreadId id, char *pName, size_t size)
 
LIBCOM_API void epicsThreadMap (EPICS_THREAD_HOOK_ROUTINE func)
 
LIBCOM_API void epicsStdCall epicsThreadShowAll (unsigned level)
 
LIBCOM_API void epicsStdCall epicsThreadShow (epicsThreadId id, unsigned level)
 
LIBCOM_API void epicsStdCall epicsThreadOnce (epicsThreadOnceId *id, void(*func)(void *), void *arg)
 
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate ()
 
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete (epicsThreadPrivateId p)
 
LIBCOM_API void epicsStdCall epicsThreadPrivateSet (epicsThreadPrivateId pPvt, void *pVal)
 
LIBCOM_API void *epicsStdCall epicsThreadPrivateGet (epicsThreadPrivateId pPvt)
 
LIBCOM_API int epicsThreadGetCPUs (void)
 

Macro Definition Documentation

#define _WIN32_WINNT   0x400 /* No support for W95 */

Definition at line 22 of file osdThread.c.

#define EPICS_THREAD_ONCE_DONE   & threadOnceComplete
#define osdOrdinaryPriorityStateCount   5u

Definition at line 67 of file osdThread.c.

#define osdRealtimePriorityStateCount   14u

Definition at line 77 of file osdThread.c.

#define STACK_SIZE (   f)    (f * 0x10000 * sizeof(void *))
#define STACK_SIZE_PARAM_IS_A_RESERVATION   0x00010000

Definition at line 64 of file osdThread.c.

#define STRICT

Definition at line 20 of file osdThread.c.

#define VC_EXTRALEAN

Definition at line 19 of file osdThread.c.

Typedef Documentation

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 548 of file osdThread.c.

552 {
553  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
554  win32ThreadParam * pParmWIN32;
555  unsigned int stackSize;
556  int osdPriority;
557  DWORD wstat;
558  BOOL bstat;
559 
560  if ( ! pGbl ) {
561  return NULL;
562  }
563 
564  if (!opts) {
565  static const epicsThreadOpts opts_default = EPICS_THREAD_OPTS_INIT;
566  opts = &opts_default;
567  }
568  stackSize = opts->stackSize;
569  if (stackSize <= epicsThreadStackBig)
570  stackSize = epicsThreadGetStackSize(stackSize);
571 
572  pParmWIN32 = epicsThreadParmCreate ( pName );
573  if ( pParmWIN32 == 0 ) {
574  return ( epicsThreadId ) pParmWIN32;
575  }
576  pParmWIN32->funptr = pFunc;
577  pParmWIN32->parm = pParm;
578  pParmWIN32->epicsPriority = opts->priority;
579  if(opts->joinable) {
580  pParmWIN32->joinable = 1;
581  epicsAtomicIncrIntT(&pParmWIN32->refcnt);
582  }
583 
584  {
585  unsigned threadId;
586  pParmWIN32->handle = (HANDLE) _beginthreadex (
587  0, stackSize, epicsWin32ThreadEntry,
588  pParmWIN32,
589  CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
590  & threadId );
591  if ( pParmWIN32->handle == 0 ) {
592  free ( pParmWIN32 );
593  return NULL;
594  }
595  /* weird win32 interface threadId parameter inconsistency */
596  pParmWIN32->id = ( DWORD ) threadId ;
597  }
598 
599  osdPriority = epicsThreadGetOsdPriorityValue (opts->priority);
600  bstat = SetThreadPriority ( pParmWIN32->handle, osdPriority );
601  if (!bstat) {
602  CloseHandle ( pParmWIN32->handle );
603  free ( pParmWIN32 );
604  return NULL;
605  }
606 
607  EnterCriticalSection ( & pGbl->mutex );
608  ellAdd ( & pGbl->threadList, & pParmWIN32->node );
609  LeaveCriticalSection ( & pGbl->mutex );
610 
611  wstat = ResumeThread ( pParmWIN32->handle );
612  if (wstat==0xFFFFFFFF) {
613  EnterCriticalSection ( & pGbl->mutex );
614  ellDelete ( & pGbl->threadList, & pParmWIN32->node );
615  LeaveCriticalSection ( & pGbl->mutex );
616  CloseHandle ( pParmWIN32->handle );
617  free ( pParmWIN32 );
618  return NULL;
619  }
620 
621  return ( epicsThreadId ) pParmWIN32;
622 }
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass stackSizeClass)
Definition: osdThread.c:466
HANDLE handle
Definition: osdThread.c:49
#define STACK_SIZE_PARAM_IS_A_RESERVATION
Definition: osdThread.c:64
EPICSTHREADFUNC funptr
Definition: osdThread.c:50
ELLNODE node
Definition: osdThread.h:24
#define NULL
Definition: catime.c:38
unsigned int joinable
Definition: epicsThread.h:158
ELLLIST threadList
Definition: osdThread.c:42
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
CRITICAL_SECTION mutex
Definition: osdThread.c:41
unsigned int stackSize
Definition: epicsThread.h:154
void * parm
Definition: osdThread.c:51
char * pName
Definition: osdThread.c:52
unsigned int priority
Definition: epicsThread.h:150
#define EPICS_THREAD_OPTS_INIT
Definition: epicsThread.h:167
EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT(int *pTarget)
unsigned epicsPriority
Definition: osdThread.c:54
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
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 249 of file osdThread.c.

250 {
251  _endthread ();
252 }
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 1114 of file osdThread.c.

1115 {
1116  SYSTEM_INFO sysinfo;
1117  GetSystemInfo(&sysinfo);
1118  if (sysinfo.dwNumberOfProcessors > 0)
1119  return sysinfo.dwNumberOfProcessors;
1120  return 1;
1121 }
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 850 of file osdThread.c.

851 {
852  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
853  win32ThreadParam * pParm;
854 
855  if ( ! pGbl ) {
856  return 0;
857  }
858 
859  EnterCriticalSection ( & pGbl->mutex );
860 
861  for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList );
862  pParm; pParm = ( win32ThreadParam * ) ellNext ( & pParm->node ) ) {
863  if ( pParm->pName ) {
864  if ( strcmp ( pParm->pName, pName ) == 0 ) {
865  break;
866  }
867  }
868  }
869 
870  LeaveCriticalSection ( & pGbl->mutex );
871 
872  /* !!!! warning - the thread parm could vanish at any time !!!! */
873 
874  return ( epicsThreadId ) pParm;
875 }
ELLNODE node
Definition: osdThread.h:24
ELLLIST threadList
Definition: osdThread.c:42
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
CRITICAL_SECTION mutex
Definition: osdThread.c:41
char * pName
Definition: osdThread.c:52
#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 834 of file osdThread.c.

835 {
836  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
837  win32ThreadParam * pParm;
838 
839  assert ( pGbl );
840 
841  pParm = ( win32ThreadParam * ) TlsGetValue (
843  if ( ! pParm ) {
844  pParm = epicsThreadImplicitCreate ();
845  assert ( pParm ); /* very dangerous to allow non-unique thread id into use */
846  }
847  return ( epicsThreadId ) pParm;
848 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
DWORD tlsIndexThreadLibraryEPICS
Definition: osdThread.c:43
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 907 of file osdThread.c.

909 {
910  win32ThreadParam * pParm = ( win32ThreadParam * ) id;
911 
912  if ( size ) {
913  size_t sizeMinusOne = size-1;
914  strncpy ( pName, pParm->pName, sizeMinusOne );
915  pName [sizeMinusOne] = '\0';
916  }
917 }
char * pName
Definition: osdThread.c:52
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 881 of file osdThread.c.

882 {
883  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
884  win32ThreadParam * pParm;
885 
886  if ( ! pGbl ) {
887  return "thread library not initialized";
888  }
889 
890  pParm = ( win32ThreadParam * )
891  TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
892  if ( ! pParm ) {
893  pParm = epicsThreadImplicitCreate ();
894  }
895 
896  if ( pParm ) {
897  if ( pParm->pName ) {
898  return pParm->pName;
899  }
900  }
901  return "anonymous";
902 }
DWORD tlsIndexThreadLibraryEPICS
Definition: osdThread.c:43
char * pName
Definition: osdThread.c:52
LIBCOM_API unsigned epicsStdCall epicsThreadGetPriority ( epicsThreadId  id)

Return thread OSI priority

Definition at line 704 of file osdThread.c.

705 {
706  win32ThreadParam * pParm = ( win32ThreadParam * ) id;
707  return pParm->epicsPriority;
708 }
unsigned epicsPriority
Definition: osdThread.c:54
LIBCOM_API unsigned epicsStdCall epicsThreadGetPrioritySelf ( void  )

Return thread OSI priority

Definition at line 713 of file osdThread.c.

714 {
715  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
716  win32ThreadParam * pParm;
717 
718  assert ( pGbl );
719 
720  pParm = ( win32ThreadParam * )
721  TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
722  if ( ! pParm ) {
723  pParm = epicsThreadImplicitCreate ();
724  }
725  if ( pParm ) {
726  return pParm->epicsPriority;
727  }
728  else {
729  int win32ThreadPriority =
730  GetThreadPriority ( GetCurrentThread () );
731  assert ( win32ThreadPriority != THREAD_PRIORITY_ERROR_RETURN );
732  return epicsThreadGetOsiPriorityValue ( win32ThreadPriority );
733  }
734 }
int epicsThreadGetOsiPriorityValue(int ossPriority)
Definition: osdThread.c:85
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
DWORD tlsIndexThreadLibraryEPICS
Definition: osdThread.c:43
unsigned epicsPriority
Definition: osdThread.c:54
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 420 of file osdThread.c.

421 {
422  #define STACK_SIZE(f) (f * 0x10000 * sizeof(void *))
423  static const unsigned stackSizeTable[epicsThreadStackBig+1] = {
424  STACK_SIZE(1), STACK_SIZE(2), STACK_SIZE(4)
425  };
426 
427  if (stackSizeClass<epicsThreadStackSmall) {
428  fprintf ( stderr,
429  "epicsThreadGetStackSize illegal argument (too small)");
430  return stackSizeTable[epicsThreadStackBig];
431  }
432 
433  if (stackSizeClass>epicsThreadStackBig) {
434  fprintf ( stderr,
435  "epicsThreadGetStackSize illegal argument (too large)");
436  return stackSizeTable[epicsThreadStackBig];
437  }
438 
439  return stackSizeTable[stackSizeClass];
440 }
#define STACK_SIZE(f)
#define stderr
Definition: epicsStdio.h:32
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 390 of file osdThread.c.

391 {
392  const DWORD priorityClass = GetPriorityClass ( GetCurrentProcess () );
394  unsigned stateCount;
395  unsigned magnitude;
396 
397  if ( priorityClass == REALTIME_PRIORITY_CLASS ) {
398  stateCount = osdRealtimePriorityStateCount;
399  }
400  else {
401  stateCount = osdOrdinaryPriorityStateCount;
402  }
403 
404  magnitude = osdPriorityMagFromPriorityOSI ( priority, stateCount );
405 
406  if ( magnitude > 0u ) {
407  *pPriorityJustBelow = osiPriorityMagFromMagnitueOSD ( magnitude - 1u, stateCount );
409  }
410  else {
412  }
413  return status;
414 }
#define osdRealtimePriorityStateCount
Definition: osdThread.c:77
epicsThreadBooleanStatus
Definition: epicsThread.h:93
pvd::Status status
#define osdOrdinaryPriorityStateCount
Definition: osdThread.c:67
LIBCOM_API int epicsStdCall epicsThreadIsEqual ( epicsThreadId  id1,
epicsThreadId  id2 
)

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

Definition at line 749 of file osdThread.c.

750 {
751  win32ThreadParam * pParm1 = ( win32ThreadParam * ) id1;
752  win32ThreadParam * pParm2 = ( win32ThreadParam * ) id2;
753  return ( id1 == id2 && pParm1->id == pParm2->id );
754 }
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 759 of file osdThread.c.

760 {
761  win32ThreadParam *pParm = ( win32ThreadParam * ) id;
762  DWORD exitCode;
763  BOOL stat;
764 
765  stat = GetExitCodeThread ( pParm->handle, & exitCode );
766  if ( stat ) {
767  if ( exitCode != STILL_ACTIVE ) {
768  return 1;
769  }
770  else {
771  return pParm->isSuspended;
772  }
773  }
774  else {
775  return 1;
776  }
777 }
HANDLE handle
Definition: osdThread.c:49
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 360 of file osdThread.c.

361 {
362  const DWORD priorityClass = GetPriorityClass ( GetCurrentProcess () );
364  unsigned stateCount;
365  unsigned magnitude;
366 
367  if ( priorityClass == REALTIME_PRIORITY_CLASS ) {
368  stateCount = osdRealtimePriorityStateCount;
369  }
370  else {
371  stateCount = osdOrdinaryPriorityStateCount;
372  }
373 
374  magnitude = osdPriorityMagFromPriorityOSI ( priority, stateCount );
375 
376  if ( magnitude < ( stateCount - 1 ) ) {
377  *pPriorityJustAbove = osiPriorityMagFromMagnitueOSD ( magnitude + 1u, stateCount );
379  }
380  else {
382  }
383  return status;
384 }
#define osdRealtimePriorityStateCount
Definition: osdThread.c:77
epicsThreadBooleanStatus
Definition: epicsThread.h:93
pvd::Status status
#define osdOrdinaryPriorityStateCount
Definition: osdThread.c:67
LIBCOM_API void epicsThreadMap ( EPICS_THREAD_HOOK_ROUTINE  func)

Call func once for every known thread.

Definition at line 982 of file osdThread.c.

983 {
984  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
985  win32ThreadParam * pParm;
986 
987  if ( ! pGbl ) {
988  return;
989  }
990 
991  EnterCriticalSection ( & pGbl->mutex );
992 
993  for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList );
994  pParm; pParm = ( win32ThreadParam * ) ellNext ( & pParm->node ) ) {
995  func ( ( epicsThreadId ) pParm );
996  }
997 
998  LeaveCriticalSection ( & pGbl->mutex );
999 }
ELLNODE node
Definition: osdThread.h:24
ELLLIST threadList
Definition: osdThread.c:42
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
CRITICAL_SECTION mutex
Definition: osdThread.c:41
#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 624 of file osdThread.c.

625 {
626  win32ThreadParam * pParmWIN32 = id;
627 
628  if(!id) {
629  /* no-op */
630  } else if(epicsAtomicCmpAndSwapIntT(&id->joinable, 1, 0)!=1) {
631  if(epicsThreadGetIdSelf()==id) {
632  fprintf(stderr, "Warning: %s thread self-join of unjoinable\n", pParmWIN32->pName);
633 
634  } else {
635  /* try to error nicely, however in all likelyhood de-ref of
636  * 'id' has already caused SIGSEGV as we are racing thread exit,
637  * which free's 'id'.
638  */
639  cantProceed("Error: %s thread not joinable.\n", pParmWIN32->pName);
640  }
641 
642  } else if(epicsThreadGetIdSelf() != id) {
643  DWORD status = WaitForSingleObject(pParmWIN32->handle, INFINITE);
644  if(status != WAIT_OBJECT_0) {
645  /* TODO: signal error? */
646  }
647 
648  epicsParmCleanupWIN32(pParmWIN32);
649  } else {
650  /* join self silently does nothing */
651  epicsParmCleanupWIN32(pParmWIN32);
652  }
653 }
HANDLE handle
Definition: osdThread.c:49
pvd::Status status
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT(int *pTarget, int oldVal, int newVal)
char * pName
Definition: osdThread.c:52
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
LIBCOM_API void epicsStdCall epicsThreadOnce ( epicsThreadOnceId id,
void(*)(void *)  func,
void *  arg 
)

Definition at line 1036 of file osdThread.c.

1038 {
1039  static struct epicsThreadOSD threadOnceComplete;
1040  #define EPICS_THREAD_ONCE_DONE & threadOnceComplete
1041  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
1042 
1043  assert ( pGbl );
1044 
1045  EnterCriticalSection ( & pGbl->mutex );
1046 
1047  if ( *id != EPICS_THREAD_ONCE_DONE ) {
1048  if ( *id == EPICS_THREAD_ONCE_INIT ) { /* first call */
1049  *id = epicsThreadGetIdSelf(); /* mark active */
1050  LeaveCriticalSection ( & pGbl->mutex );
1051  func ( arg );
1052  EnterCriticalSection ( & pGbl->mutex );
1053  *id = EPICS_THREAD_ONCE_DONE; /* mark done */
1054  } else if ( *id == epicsThreadGetIdSelf() ) {
1055  LeaveCriticalSection ( & pGbl->mutex );
1056  cantProceed( "Recursive epicsThreadOnce() initialization\n" );
1057  } else
1058  while ( *id != EPICS_THREAD_ONCE_DONE ) {
1059  /* Another thread is in the above func(arg) call. */
1060  LeaveCriticalSection ( & pGbl->mutex );
1062  EnterCriticalSection ( & pGbl->mutex );
1063  }
1064  }
1065  LeaveCriticalSection ( & pGbl->mutex );
1066 }
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum()
Query a value approximating the OS timer/scheduler resolution.
Definition: osdThread.c:981
#define EPICS_THREAD_ONCE_DONE
#define EPICS_THREAD_ONCE_INIT
Definition: epicsThread.h:109
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate ( void  )

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

Definition at line 1071 of file osdThread.c.

1072 {
1073  epicsThreadPrivateOSD *p = ( epicsThreadPrivateOSD * ) malloc ( sizeof ( *p ) );
1074  if ( p ) {
1075  p->key = TlsAlloc ();
1076  if ( p->key == 0xFFFFFFFF ) {
1077  free ( p );
1078  p = 0;
1079  }
1080  }
1081  return p;
1082 }
LIBCOM_API void epicsStdCall epicsThreadPrivateDelete ( epicsThreadPrivateId  id)

Free a thread local variable

Definition at line 1087 of file osdThread.c.

1088 {
1089  BOOL stat = TlsFree ( p->key );
1090  assert ( stat );
1091  free ( p );
1092 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API void* epicsStdCall epicsThreadPrivateGet ( epicsThreadPrivateId  )

Fetch the current value of a thread local variable

Definition at line 1106 of file osdThread.c.

1107 {
1108  return ( void * ) TlsGetValue ( pPvt->key );
1109 }
LIBCOM_API void epicsStdCall epicsThreadPrivateSet ( epicsThreadPrivateId  ,
void *   
)

Update thread local variable

Definition at line 1097 of file osdThread.c.

1098 {
1099  BOOL stat = TlsSetValue ( pPvt->key, (void *) pVal );
1100  assert (stat);
1101 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
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 278 of file osdThread.c.

279 {}
LIBCOM_API void epicsStdCall epicsThreadResume ( epicsThreadId  id)

Resume a thread suspended with epicsThreadSuspendSelf()

Definition at line 683 of file osdThread.c.

684 {
685  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
686  win32ThreadParam * pParm = ( win32ThreadParam * ) id;
687  DWORD stat;
688 
689  assert ( pGbl );
690 
691  EnterCriticalSection ( & pGbl->mutex );
692 
693  stat = ResumeThread ( pParm->handle );
694  pParm->isSuspended = 0;
695 
696  LeaveCriticalSection ( & pGbl->mutex );
697 
698  assert ( stat != 0xFFFFFFFF );
699 }
HANDLE handle
Definition: osdThread.c:49
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
CRITICAL_SECTION mutex
Definition: osdThread.c:41
LIBCOM_API void epicsStdCall epicsThreadSetPriority ( epicsThreadId  id,
unsigned  priority 
)

Definition at line 739 of file osdThread.c.

740 {
741  win32ThreadParam * pParm = ( win32ThreadParam * ) id;
742  BOOL stat = SetThreadPriority ( pParm->handle, epicsThreadGetOsdPriorityValue (priority) );
743  assert (stat);
744 }
HANDLE handle
Definition: osdThread.c:49
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
LIBCOM_API void epicsStdCall epicsThreadShow ( epicsThreadId  id,
unsigned  level 
)

Definition at line 1027 of file osdThread.c.

1028 {
1029  epicsThreadShowInfo ( 0, level );
1030  epicsThreadShowInfo ( id, level );
1031 }
LIBCOM_API void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
LIBCOM_API void epicsStdCall epicsThreadShowAll ( unsigned  level)

Definition at line 1004 of file osdThread.c.

1005 {
1006  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
1007  win32ThreadParam * pParm;
1008 
1009  if ( ! pGbl ) {
1010  return;
1011  }
1012 
1013  EnterCriticalSection ( & pGbl->mutex );
1014 
1015  epicsThreadShowInfo ( 0, level );
1016  for ( pParm = ( win32ThreadParam * ) ellFirst ( & pGbl->threadList );
1017  pParm; pParm = ( win32ThreadParam * ) ellNext ( & pParm->node ) ) {
1018  epicsThreadShowInfo ( ( epicsThreadId ) pParm, level );
1019  }
1020 
1021  LeaveCriticalSection ( & pGbl->mutex );
1022 }
ELLNODE node
Definition: osdThread.h:24
ELLLIST threadList
Definition: osdThread.c:42
LIBCOM_API void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level)
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
CRITICAL_SECTION mutex
Definition: osdThread.c:41
#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 782 of file osdThread.c.

783 {
784  static const unsigned mSecPerSec = 1000;
785  DWORD milliSecDelay;
786 
787  if ( seconds > 0.0 ) {
788  seconds *= mSecPerSec;
789  seconds += 0.99999999; /* 8 9s here is optimal */
790  milliSecDelay = ( seconds >= INFINITE ) ?
791  INFINITE - 1 : ( DWORD ) seconds;
792  }
793  else { /* seconds <= 0 or NAN */
794  milliSecDelay = 0u;
795  }
796  Sleep ( milliSecDelay );
797 }
const unsigned mSecPerSec
Definition: fdManager.cpp:34
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 802 of file osdThread.c.

803 {
804  /*
805  * Its worth noting here that the sleep quantum on windows can
806  * mysteriously get better. I eventually tracked this down to
807  * codes that call timeBeginPeriod(1). Calling timeBeginPeriod()
808  * specifying a better timer resolution also increases the interrupt
809  * load. This appears to be related to java applet activity.
810  * The function timeGetDevCaps can tell us the range of periods
811  * that can be specified to timeBeginPeriod, but alas there
812  * appears to be no way to find out what the value of the global
813  * minimum of all timeBeginPeriod calls for all processes is.
814  */
815  static const double secPerTick = 100e-9;
816  DWORD adjustment;
817  DWORD delay;
818  BOOL disabled;
819  BOOL success;
820 
821  success = GetSystemTimeAdjustment (
822  & adjustment, & delay, & disabled );
823  if ( success ) {
824  return delay * secPerTick;
825  }
826  else {
827  return 0.0;
828  }
829 }
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf ( void  )

Block the current thread until epicsThreadResume().

Definition at line 658 of file osdThread.c.

659 {
660  win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
661  win32ThreadParam * pParm;
662  DWORD stat;
663 
664  assert ( pGbl );
665 
666  pParm = ( win32ThreadParam * )
667  TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
668  if ( ! pParm ) {
669  pParm = epicsThreadImplicitCreate ();
670  }
671  if ( pParm ) {
672  EnterCriticalSection ( & pGbl->mutex );
673  pParm->isSuspended = 1;
674  LeaveCriticalSection ( & pGbl->mutex );
675  }
676  stat = SuspendThread ( GetCurrentThread () );
677  assert ( stat != 0xFFFFFFFF );
678 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
DWORD tlsIndexThreadLibraryEPICS
Definition: osdThread.c:43
CRITICAL_SECTION mutex
Definition: osdThread.c:41
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
void setThreadName ( DWORD  dwThreadID,
LPCSTR  szThreadName 
)

Definition at line 26 of file setThreadName.cpp.

27 {
28 #if _MSC_VER >= 1300 && defined ( _DEBUG )
29  typedef struct tagTHREADNAME_INFO
30  {
31  DWORD dwType; // must be 0x1000
32  LPCSTR szName; // pointer to name (in user addr space)
33  DWORD dwThreadID; // thread ID (-1=caller thread)
34  DWORD dwFlags; // reserved for future use, must be zero
35  } THREADNAME_INFO;
36  THREADNAME_INFO info;
37  info.dwType = 0x1000;
38  info.szName = szThreadName;
39  info.dwThreadID = dwThreadID;
40  info.dwFlags = 0;
41 
42  __try
43  {
44  RaiseException( 0x406D1388, 0,
45  sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info );
46  }
47  __except(EXCEPTION_CONTINUE_EXECUTION)
48  {
49  }
50 #endif
51 }