Chapter 20
libCom OSI libraries
20.1 Overview
Most code in base is operating system independent, i.e. the code is exactly the same for all supported operating
systems. This is accomplished by providing epics-specific APIs for facilities that are different on the various
systems. These APIs are called Operating System Independent, or OSI, and are part of libCom. The OSI APIs have
multiple implementations, which are Operating System Dependent or OSD. Some APIs are implemented using
the features of a particular compiler that is supported on multiple operating systems. For example the GNU
Compiler Collection (GCC) is used for compiling many targets and provides a common GCC-specific API for some
features. Base now makes it possible to use compiler-specific as well as OS-specific code to implement the OSI
APIs.
20.1.1 OSI source directory
Directory <base>/src/libCom/osi contains the code for the operating system independent libraries. The structure of this
directory is:
osi/
⋆.h
⋆.c
⋆.cpp
compiler/
borland/
clang/
default/
gcc/
msvc/
solStudio/
os/
Linux/
Darwin/
RTEMS/
WIN32/
default/
posix/
solaris/
vxWorks/
Code for additional compilers and operating systems may also be present.
20.1.2 Rules for building OSI code
The src/libCom/osi directory contains source and header files that provide common definitions for the OSI
APIs. The directories under osi/compiler contain compiler-specific files that implement some of the OSI
APIs. The directories under osi/os contain operating-system-specific files that implement the remaining OSI
APIs.
Header files residing under src/libCom/osi are installed into include as follows:
- Header files in the osi directory are installed into include
- Header files from an OS-specific directory osi/os/<os> are installed into include/os/<os>. The search
order for locating the specific file to be installed is:
- osi/os/<os>
- osi/os/posix — if the target uses Posix APIs
- osi/os/default
- Header files from a compiler-specific directory osi/compiler/<cmplr> are installed into the directory
include/compiler/<cmplr>. The search order for locating the specific file to be installed is:
- osi/compiler/<cmplr>
- osi/compiler/default
The search order for locating OSD source files is:
- osi/compiler/<cmplr>
- osi/compiler/default
- osi/os/<os>
- osi/os/posix
- osi/os/default
20.1.3 Locating OSI header files.
When code is compiled, the search order for locating header files in base/include is:
- include/compiler/<cmplr>
- include/os/<os>
- include
20.2 epicsAssert
This is an enhanced version of ANSI C’s assert facility. To use this, replace:
with
20.2.1 Runtime Assertion Checks
The same assert(expression) macro is used as with the ANSI header to test a run-time assertion.
If a run-time assertion check finds the expression false, it calls errlog indicating the program’s author, file
name, and line number. Each OS provides specialized instructions assisting the user to diagnose the problem
and generate a good bug report. For instance, under vxWorks there are instructions on how to generate a stack
trace; on posix there are instructions about saving the core file. After printing the message, the calling thread is
suspended.
To provide the author’s name for the message, before including the epicsAssert.h file define a preprocessor macro named
epicsAssertAuthor as a string containing the name and email address to be contacted.
20.2.2 Compile-time Assertion Checks
The C or C++ compiler can be used to evaluate and check a static expression at compile-time. Static assertions may only be
placed where a variable declaration is valid, and can only test certain kinds of constant expressions. A static assertion looks like
this:
STATIC_ASSERT(expression);
If the expression evaluates as false, the compiler will be presented with an illegal variable declaration using the name
static_assert_failed_at_line_<n> and so should halt compilation at that point.
20.3 epicsAtomic
This is an operating system and compiler independent interface to an operating system and or compiler dependent
implementation of several atomic primitives. Currently, only increment, decrement, add, subtract, compare-and-swap, and
test-and-set primitives have been implemented as appropriate for the C primitive types of int, size_t, and void ⋆
pointer.
These primitives can be safely used in multithreaded programs on symmetric multiprocessing (SMP) systems. Where possible
the primitives are implemented with compiler intrinsic wrappers for architecture specific instructions. Otherwise they are
implemented with OS specific functions and otherwise, when lacking a sufficiently capable OS specific interface, then in some
rare situations a mutual exclusion primitive is used for synchronization.
In operating systems environments which allow C code to run at interrupt level the implementation must use interrupt level
invokable CPU instruction primitives.
All C++ functions are implemented in the namespace atomics which is nested inside of namespace epics.
20.3.1 C Callable Interface
void epicsAtomicReadMemoryBarrier (); void epicsAtomicWriteMemoryBarrier (); size_t epicsAtomicIncrSizeT ( size_t ⋆ pTarget ); int epicsAtomicIncrIntT ( int ⋆ pTarget ); size_t epicsAtomicDecrSizeT ( size_t ⋆ pTarget ); int epicsAtomicDecrIntT ( int ⋆ pTarget ); size_t epicsAtomicAddSizeT ( size_t ⋆ pTarget, size_t delta ); size_t epicsAtomicSubSizeT ( size_t ⋆ pTarget, size_t delta ); int epicsAtomicAddIntT ( int ⋆ pTarget, int delta ); void epicsAtomicSetSizeT ( size_t ⋆ pTarget, size_t newValue ); void epicsAtomicSetIntT ( int ⋆ pTarget, int newValue ); void epicsAtomicSetPtrT ( EpicsAtomicPtrT ⋆ pTarget, EpicsAtomicPtrT newValue ); size_t epicsAtomicGetSizeT ( const size_t ⋆ pTarget ); int epicsAtomicGetIntT ( const int ⋆ pTarget ); EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT ⋆ pTarget ); size_t epicsAtomicCmpAndSwapSizeT ( size_t ⋆ pTarget, size_t oldVal, size_t newVal ); int epicsAtomicCmpAndSwapIntT ( int ⋆ pTarget, int oldVal, int newVal ); EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT ⋆ pTarget, EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ); int epicsAtomicTestAndSet ( int ⋆ pTarget );
C Function |
C++ Function |
Meaning |
|
|
|
epicsAtomicReadMemoryBarrier |
readMemoryBarrier |
Load target into cache. |
epicsAtomicWriteMemoryBarrier |
writeMemoryBarrier |
Push cache version of target into target. |
epicsAtomicIncrXxxx |
increment |
Lock out other SMP processors from accessing the
target, load the target into cache, add one to the target,
flush cache to the target, allow other SMP processors
to access the target, and return the new value of the
target as modified by this operation. |
epicsAtomicDecrXxxx |
decrement |
Lock out other smp processors from accessing the
target, load the target into cache, subtract one from
the target, flush cache to the target, allow other SMP
processors to access the target, and return the new
value of target as modified by this operation. |
epicsAtomicAddXxxx |
add |
Lock out other SMP processors from accessing the
target, load the target into cache, add delta to the
target, flush the cache to the target, allow other SMP
processors to access the target, return new value of
target as modified by this operation. |
epicsAtomicSubXxxx |
subtract |
Lock out other SMP processors from accessing the
target, load the target into cache, subtract delta from
the target, flush the cache to the target, allow other
SMP processors to access the target, return new value
of target as modified by this operation. |
epicsAtomicSetXxxx |
set |
Set the cached version of target, and flush the cache to
the target. |
epicsAtomicGetXxxx |
get |
Fetch the target into cache, and return the cached
value. |
epicsAtomicCmpAndSwapXxxx |
compareAndSwap |
Lock out other SMP processors from accessing the
target, load the target into cache, if the target is equal
to oldVal set the target to newVal, flush cache to the
target, allow other SMP processors to access the target,
and return the original value stored in the target. |
epicsAtomicTestAndSet |
testAndSet |
Lock out other SMP processors from accessing the
target, load the target into cache, if the target value
is logical false (zero) set the target to be logical true,
flush cache to the target, allow other SMP processors
to access the target, and return the original value stored
in the target. |
|
|
|
|
| |
|
20.4 epicsEndian
epicsEndian.h provides an operating-system independent means of discovering the native byte order of the CPU which the
compiler is targeting, and works in both C and C++ code. It defines the following preprocessor macros, the values of which are
integers:
- EPICS_ENDIAN_LITTLE
- EPICS_ENDIAN_BIG
- EPICS_BYTE_ORDER
- EPICS_FLOAT_WORD_ORDER
The latter two macros are defined to be one or other of the first two, and may be compared with them to determine conditional
compilation or execution of code that performs byte or word swapping as necessary.
#if (EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG) /⋆ ... ⋆/ #else /⋆ EPICS_ENDIAN_LITTLE ⋆/ /⋆ ... ⋆/ #endif /⋆ EPICS_BYTE_ORDER ⋆/
20.5 epicsEvent
epicsEvent.h defines the C++ and C APIs for a simple binary semaphore. If multiple threads are waiting on the same
event, only one of them will be woken when the event is signalled.
20.5.1 C++ Interface
typedef enum { epicsEventOK = 0, epicsEventWaitTimeout, epicsEventError } epicsEventStatus; /⋆ Backwards compatibility ⋆/ #define epicsEventWaitStatus epicsEventStatus #define epicsEventWaitOK epicsEventOK #define epicsEventWaitError epicsEventError typedef enum { epicsEventEmpty, epicsEventFull } epicsEventInitialState; class epicsEvent { public: epicsEvent ( epicsEventInitialState initial = epicsEventEmpty ); ~epicsEvent (); void trigger (); void signal () { this->trigger(); } void wait (); /⋆ blocks until full ⋆/ bool wait ( double timeOut ); /⋆ false if still empty at time out ⋆/ bool tryWait (); /⋆ false if empty ⋆/ void show ( unsigned level ) const; class invalidSemaphore; /⋆ exception payload ⋆/ private: ... };
Method |
Meaning |
|
|
epicsEvent |
An epicsEvent can be created empty or full. If it is created empty then a wait issued before
a trigger will block. If created full then the first wait will always succeed. Multiple triggers
may be issued between waits but have the same effect as a single trigger. |
~epicsEvent |
Remove the event and any resources it uses. Any further use of the semaphore result in
unknown (most certainly bad) behavior. No outstanding take can be active when this call is
made. |
trigger |
Trigger the event i.e. ensures that the next or current call to wait completes. This method
may be called from a vxWorks or RTEMS interrupt handler. |
signal |
A synonym for trigger, provided for backwards compatibility. |
wait() |
Wait for the event to be triggered. |
wait(double timeOut) |
Similar to wait except that if event does not happen the call completes after the specified
time out. The return value is true) if the event was triggered, false if it timed out. |
tryWait() |
Similar to wait except that if event has not already been triggered the call completes
immediately. The return value is true if an unused event has already been signalled, false if
not. |
show |
Display information about the epicsEvent. The information displayed is architecture
dependent. |
|
|
|
|
|
The primary use of an event semaphore is for thread synchronization. An example of using an event semaphore is a consumer
thread that processes requests from one or more producer threads. For example:
- When creating the consumer thread also create an epicsEvent.
epicsEvent ⋆pevent = new epicsEvent;
- The consumer thread has code containing:
while(1) { pevent->wait(); while(/⋆ more work ⋆/) { /⋆ process work ⋆/ } }
- Producers create requests and issue the statement:
20.5.2 C Interface
epicsEventId epicsEventCreate(epicsEventInitialState initialState); epicsEventId epicsEventMustCreate(epicsEventInitialState initialState); void epicsEventDestroy(epicsEventId id); epicsEventStatus epicsEventTrigger(epicsEventId id); void epicsEventMustTrigger(epicsEventId id); #define epicsEventSignal(ID) epicsEventMustTrigger(ID) epicsEventStatus epicsEventWait(epicsEventId id); void epicsEventMustWait(epicsEventId id); epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut); epicsEventStatus epicsEventTryWait(epicsEventId id); void epicsEventShow(epicsEventId id, unsigned int level);
The C routines shown above generally correspond to one of the C++ methods. The epicsEventSignal macro
provides backwards compatibility. The routines epicsEventMustCreate, epicsEventMustTrigger and
epicsEventMustWait do not return if they fail.
20.6 epicsFindSymbol
epicsFindSymbol.h contains the following definitions:
void ⋆ epicsFindSymbol(const char ⋆name); void ⋆ epicsLoadLibrary(const char ⋆name); const char ⋆epicsLoadError(void);
Function |
Meaning |
|
|
epicsFindSymbol |
Return the address of the named variable |
epicsLoadLibrary |
Load named shared library |
epicsLoadError |
Returns an error string if a library load fails |
|
|
|
|
|
The registry, described in another chapter, provides a way to find and return the address referred to by a registered symbol.
Symbols that have not been explicitly registered may not be found. If the registry is asked for a name that has not been
registered, it calls epicsFindSymbol. If epicsFindSymbol can locate the symbol, it returns the associated address,
otherwise it returns null.
On vxWorks epicsFindSymbol calls symFindByName. On Linux, Darwin and Solaris it calls dlsym. The default
version just returns null, i.e. it always fails.
The epicsLoadLibrary routine can be used to load a named library. Note that the library name may be
different on different operating systems. This routine is implemented on vxWorks, Linux, Darwin, Windows and
Solaris.
If epicsLoadLibrary fails, the routine epicsLoadError can be used to fetch a printable string that describes the
reason for the failure. Note that this library loading API is not thread-safe and should not be used in circumstances where
multiple threads might try to use it at the same time.
20.7 epicsGeneralTime
The generalTime framework provides a mechanism for several time providers to be present within the system. There are
two types of provider, one type for the current time and one type for providing Time Event times. Each time
provider has a priority, and installed providers are queried in priority order whenever a time is requested, until one
returns successfully. Thus there is a fallback from higher priority providers (smaller value of priority) to lower
priority providers (larger value of priority) if the higher priority ones fail. Each architecture has a “last resort”
provider, installed at priority 999, usually based on the system clock, which is used in the absence of any other
provider.
Targets running vxWorks and RTEMS have an NTP provider installed at priority 100.
Registered providers may also add an interrupt-safe routine to be called from the epicsTimeGetCurrentInt() or
epicsTimeGetEventInt() API routines. These interfaces do not check the priority queue, and will only succeed if the
last-used provider has registered a suitable routine.
There are two interfaces to this framework, epicsGeneralTime.h for consumers that wish to get a time and query the
framework, and generalTimeSup.h for providers that supply timestamps.
20.7.1 Consumer interface
The epicsGeneralTime.h header contains the following:
void generalTime_Init(void); int installLastResortEventProvider(void); void generalTimeResetErrorCounts(void); int generalTimeGetErrorCounts(void); const char ⋆ generalTimeHighestCurrentName(void); const char ⋆ generalTimeCurrentProviderName(void); const char ⋆ generalTimeEventProviderName(void); /⋆ Original names, for compatibility ⋆/ #define generalTimeCurrentTpName generalTimeCurrentProviderName #define generalTimeEventTpName generalTimeEventProviderName long generalTimeReport(int interest);
Function |
Meaning |
|
|
generalTime_Init |
Initialise the framework. This is called automatically by any function that
requires the framework. It does not need to be called explicitly. |
installLastResortEventProvider |
Install a Time Event time provider that returns the current time for any Time
Event number. This is optional as it is site policy whether the last resort for a
Time Event time in the absence of any working provider should be a failure,
or the current time. |
generalTimeResetErrorCounts |
Reset the internal counter of the number of times the time returned was earlier
than when previously requested. Used by device support for bo record with
DTYP = “General Time” and OUT = “@RSTERRCNT” |
generalTimeGetErrorCounts |
Return the internal counter of the number of times the time returned was
earlier than when previously requested. Used by device support for longin
record with DTYP = “General Time” and INP = “@GETERRCNT” |
generalTimeCurrentProviderName |
Return the name of the provider that last returned a valid current time, or
NULL if none. Used by stringin device support with DTYP = “General Time”
and INP = “@BESTTCP” |
generalTimeEventProviderName |
Return the name of the provider that last returned a valid Time Event time,
or NULL if none. Used by stringin device support with DTYP = “General
Time” and INP = “@BESTTEP” |
generalTimeHighestCurrentName |
Return the name of the registered current time provider that has the highest
priority. Used by stringin device support with DTYP = “General Time” and
INP = “@TOPTCP” |
generalTimeReport |
Provide information about the installed providers and their current best times. |
|
|
|
|
|
20.7.2 Time Provider Interface
The generalTimeSup.h header for time providers contains the following:
typedef int (⋆TIMECURRENTFUN)(epicsTimeStamp ⋆pDest); typedef int (⋆TIMEEVENTFUN)(epicsTimeStamp ⋆pDest, int event); int generalTimeRegisterCurrentProvider(const char ⋆name, int priority, TIMECURRENTFUN getTime); int generalTimeRegisterEventProvider(const char ⋆name, int priority, TIMEEVENTFUN getEvent); /⋆ Original names, for compatibility ⋆/ #define generalTimeCurrentTpRegister generalTimeRegisterCurrentProvider #define generalTimeEventTpRegister generalTimeRegisterEventProvider int generalTimeAddIntCurrentProvider(const char ⋆name, int priority, TIMECURRENTFUN getTime); int generalTimeAddIntEventProvider(const char ⋆name, int priority, TIMEEVENTFUN getEvent); int generalTimeGetExceptPriority(epicsTimeStamp ⋆pDest, int ⋆pPrio, int ignorePrio);
Function |
Meaning |
|
|
generalTimeRegisterCurrentProvider |
Register a current time provider with the framework. The getTime routine
must return epicsTimeOK if it provided a valid time, or epicsTimeERROR
if it could not. |
generalTimeRegisterEventProvider |
Register a provider of Time Event times with the framework. The getEvent
routine must return epicsTimeOK if it provided a valid time for the
requested Time Event, or epicsTimeERROR if it could not. It is an
implemetation decision by the provider whether a request for an Event that
has never happened should return an error and/or a valid timestamp. |
generalTimeAddIntCurrentProvider |
Add or replace an interrupt-safe provider routine for an already-registered
current time provider with the given name and priority. |
generalTimeAddIntEventProvider |
Add or replace an interrupt-safe provider routine for an already-registered
event time provider with the given name and priority. |
generalTimeGetExceptProirity |
Request the current time from the framework, but exclude providers with
priority ignorePrio. This allows a provider without an absolute time source
to synchronise itself with other providers that do provide an absolute time.
pPrio returns the priority of the provider that supplied the result, which may
be higher or lower than ignorePrio. |
|
|
|
|
|
If multiple providers are registered at the same priority, they will be queried in the order in which they were registered until one
is able to provide the time when requested.
Some providers may start a task that periodically synchronizes themselves with a higher priority provider, using
generalTimeGetExceptPriority() to ensure that they are themselves excluded from this time request.
Interrupt-safe providers are optional, but an IOC that needs to request the time from interrupt context must be using a current or
event time source that supports the appropriate request because only the most recently successful provider will be used (the
priority list cannot be traversed for requests made from interrupt context). The result returned by is not protected against
backwards movement.
20.7.3 Internal Interface
The generalTime framework also now provides the implementations of the following routines that are declared in
epicsTime.h:
int epicsTimeGetCurrent(epicsTimeStamp ⋆pDest); int epicsTimeGetEvent(epicsTimeStamp ⋆pDest, int eventNumber); int epicsTimeGetCurrentInt(epicsTimeStamp ⋆pDest); int epicsTimeGetEventInt(epicsTimeStamp ⋆pDest, int eventNumber);
If epicsTimeGetEvent() is called with an event number of 0 (epicsTimeEventCurrentTime) it will return the
time from the best available current time provider. Thus providers do not need to provide event times if they do not implement
an event system.
20.7.4 Example
Soft device support is provided for ai, bo, longin and stringin records. A typical example is:
record(ai, "$(IOC):GTIM_CURTIME") {
field(DESC, "Get Time")
field(DTYP, "General Time")
field(INP, "@TIME")
}
record(bo, "$(IOC):GTIM_RSTERR") {
field(DESC, "Reset ErrorCounts")
field(DTYP, "General Time")
field(OUT, "@RSTERRCNT")
}
record(longin, "$(IOC):GTIM_ERRCNT") {
field(DESC, "Get ErrorCounts")
field(DTYP, "General Time")
field(INP, "@GETERRCNT")
}
record(stringin, "$(IOC):GTIM_BESTTCP") {
field(DESC, "Best Time-Current-Provider")
field(DTYP, "General Time")
field(INP, "@BESTTCP")
}
record(stringin, "$(IOC):GTIM_BESTTEP") {
field(DESC, "Best Time-Event-Provider")
field(DTYP, "General Time")
field(INP, "@BESTTEP")
}
20.8 epicsInterrupt
epicsInterrupt.h contains the following:
20.8.1 C Interface
int epicsInterruptLock(); void epicsInterruptUnlock(int key); int epicsInterruptIsInterruptContext(); void epicsInterruptContextMessage(const char ⋆message);
Method |
Meaning |
|
|
epicsInterruptLock |
Lock interrupts and return a key to be passed to
epicsInterruptUnlock To lock the following is done. int key; ... key
= epicsInterruptLock(); ... epicsInterruptUnlock(key); |
epicsInterruptUnlock |
Unlock interrupts. |
epicsInterruptIsInterruptContext |
Return (true, false) if current context is interrupt context. |
epicsInterruptContextMessage |
Generate a message while interrupt context is true. |
|
|
|
|
|
20.8.2 Implementation notes
A vxWorks specific version is provided. It maps directly to intLib calls.
An RTEMS version is provided that maps to rtems_ calls.
A default version is provided that uses a global semaphore to lock. This version is intended for operating systems in which
iocCore will run as a multi threaded process. The global semaphore is thus only global within the process. This version is
intended for use on all except real time operating systems.
The vxWorks implementation will most likely not work on symmetric multiprocessing systems.
The reason epicsInterrupt is needed is:
- callbackRequest and scanOnce can be issued from interrupt level.
- The errlog routines can be called while at interrupt level.
20.9 epicsMath
epicsMath.h includes math.h and also ensures that isnan and isinf are defined.
20.10 epicsMessageQueue
epicsMessageQueue.h describes a C++ and a C facility for interlocked communication between threads.
20.10.1 C++ Interface
EpicsMessageQueue provides methods for sending messages between threads on a first in, first out basis. It is designed so that a
single message queue can be used with multiple writer and reader threads.
class epicsMessageQueue { public: epicsMessageQueue(unsigned int capacity, unsigned int maximumMessageSize); ~epicsMessageQueue(); int trySend(void ⋆message, unsigned int messageSize); int send(void ⋆message, unsigned int messageSize); int send(void ⋆message, unsigned int messageSize, double timeout); int tryReceive(void ⋆message, unsigned int messageBufferSize); int receive(void ⋆message, unsigned int messageBufferSize); int receive(void ⋆message, unsigned int messageBufferSize, double timeout); void show(int level) const; int pending() const; private: // Prevent compiler-generated member functions // default constructor, copy constructor, assignment operator epicsMessageQueue(); epicsMessageQueue(const epicsMessageQueue &); epicsMessageQueue& operator=(const epicsMessageQueue &); private: // Data ... };
An epicsMessageQueue cannot be assigned to, copy-constructed, or constructed without giving the capacity and
maximumMessageSize arguments. The C++ compiler will object to some of the statements below:
epicsMessageQueue mq0(); // Error: default constructor is private epicsMessageQueue mq1(10, 20); // OK epicsMessageQueue mq2(t1); // Error: copy constructor is private epicsMessageQueue ⋆pmq; // OK, pointer ⋆pmq = mq1; // Error: assignment operator is private pmq = &mq1; // OK, pointer assignment and address-of
Method |
Meaning |
|
|
epicsMessageQueue() |
Constructor. The capacity is the maximum number of messages, each containing 0 to
maximumMessageSize bytes, that can be stored in the message queue. |
~epicsMessageQueue() |
Destructor. |
trySend() |
Try to send a message. Return 0 if the message was sent to a receiver or queued for future
delivery. Return -1 if no more messages can be queued or if the message is larger than the
queue’s maximum message size. This method may be called from a vxWorks or RTEMS
interrupt handler. |
send() |
Send a message. Return 0 if the message was sent to a receiver or queued for future delivery.
Return -1 if the timeout, if any, was reached before the message could be sent or queued,
or if the message is larger than the queue’s maximum message size. |
tryReceive() |
Try to receive a message. If the message queue is non-empty, the first message on the
queue is copied to the specified location and the length of the message is returned. Returns
-1 if the message queue is empty. If the pending message is larger than the specified
messageBufferSize it may either return -1, or truncate the message. It is most efficient if the
messageBufferSize is equal to the maximumMessageSize with which the message queue
was created. |
receive() |
Wait until a message is sent and store it in the specified location. The number of bytes in
the message is returned. Returns -1 if a message is not received within the timeout interval.
If the received message is larger than the specified messageBufferSize it may either return
-1, or truncate the message. It is most efficient if the messageBufferSize is equal to the
maximumMessageSize with which the message queue was created. |
show() |
Displays some information about the message queue. The level argument controls the
amount of information dispalyed. |
pending() |
Returns the number of messages presently in the queue. |
|
|
|
|
|
20.10.2 C interface
typedef struct epicsMessageQueueOSD ⋆epicsMessageQueueId; epicsMessageQueueId epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize); void epicsMessageQueueDestroy(epicsMessageQueueId id); int epicsMessageQueueTrySend(epicsMessageQueueId id, void ⋆message, unsigned int size); int epicsMessageQueueSend(epicsMessageQueueId id, void ⋆message, unsigned int size); int epicsMessageQueueSendWithTimeout(epicsMessageQueueId id, void ⋆message, unsigned int size, double timeout); int epicsMessageQueueTryReceive(epicsMessageQueueId id, void ⋆message, unsigned int size); int epicsMessageQueueReceive(epicsMessageQueueId id, void ⋆message, unsigned int size); int epicsMessageQueueReceiveWithTimeout(epicsMessageQueueId id, void ⋆message, unsigned int size, double timeout); void epicsMessageQueueShow(epicsMessageQueueId id); int epicsMessageQueuePending(epicsMessageQueueId id);
Each C function corresponds to one of the C++ methods.
20.11 epicsMutex
epicsMutex.h contains both C++ and C descriptions for a mutual exclusion semaphore.
20.11.1 C++ Interface
typedef enum { epicsMutexLockOK, epicsMutexLockTimeout, epicsMutexLockError } epicsMutexLockStatus; #define newEpicsMutex new epicsMutex(__FILE__,__LINE__) class epicsMutex { public: epicsMutex (); epicsMutex ( const char ⋆pFileName, int lineno ); ~epicsMutex (); void lock (); /⋆ blocks until success ⋆/ bool tryLock (); /⋆ true if successful ⋆/ void unlock (); void show ( unsigned level ) const; class invalidSemaphore {}; /⋆ exception ⋆/ private: };
Method |
Meaning |
|
|
epicsMutex |
Create a mutual exclusion semaphore. |
~epicsMutex |
Remove the semaphore and any resources it uses. Any further use of the
semaphore result in unknown (most certainly bad) results. |
lock() |
Wait until the resource is free. After a successful lock additional, i.e. recursive,
locks of any type can be issued but each must have an associated unlock. |
tryLock() |
Similar to lock except that, if the resource is owned by another thread, the call
completes immediately. The return value is (false,true) if the resource (is not, is)
owned by the caller. |
unlock |
Release the resource. If a thread issues recursive locks, there must be an unlock
for each lock |
show |
Display information about the semaphore. The results are architecture dependent. |
|
|
|
|
|
Mutual exclusion semaphores are for situations requiring mutually exclusive access to resources. A mutual exclusion
semaphore may be taken recursively, i.e. can be taken more than once by the owner thread before releasing
it. Recursive takes are useful for a set of routines that call each other while working on a mutually exclusive
resource.
The newEpicsMutex macro simplifies debugging by letting the mutex store the source filename and line-number
where it was created, using the second form of the constructor. The C interface also stores this information. The
epicsMutex::show() routine can display that source location.
The typical use of a mutual exclusion semaphore is:
epicsMutex ⋆plock = newEpicsMutex; ... ... plock->lock(); /⋆ process resource ⋆/ plock->unlock();
20.11.2 C Interface
typedef struct epicsMutexOSD⋆ epicsMutexId; epicsMutexId epicsMutexCreate(void); epicsMutexId epicsMutexMustCreate (void); void epicsMutexDestroy(epicsMutexId id); void epicsMutexUnlock(epicsMutexId id); epicsMutexLockStatus epicsMutexLock(epicsMutexId id); void epicsMutexMustLock(epicsMutexId id); epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id); void epicsMutexShow(epicsMutexId id,unsigned int level); void epicsMutexShowAll(int onlyLocked,unsigned int level);
Each C routine corresponds to one of the C++ methods. epicsMutexMustCreate and epicsMutexMustLock do not
return if they fail.
20.11.3 Implementation Notes
The implementation:
- Must implement recursive locking
- May implement priority inheritance and be deletion safe
A posix version is implemented via pthreads.
20.12 epicsSpin
epicsSpin.h contains definitions for a spin lock semaphore.
20.12.1 C Interface
typedef struct epicsSpin ⋆epicsSpinId; epicsSpinId epicsSpinCreate(); void epicsSpinDestroy(epicsSpinId); void epicsSpinLock(epicsSpinId); int epicsSpinTryLock(epicsSpinId); void epicsSpinUnlock(epicsSpinId);
Method |
Meaning |
|
|
epicsSpinCreate |
Create a spin lock, allocate required resources, and initialize it to an unlocked state. |
epicsSpinDestroy() |
Remove the spin lock and any resources it uses. Any further use of the spin lock
may result in unknown (most certainly bad) behavior. The results are also undefined if
epicsSpinDestroy is used when a thread holds the lock. |
epicsSpinLock() |
Wait (by spinning, i.e. busy waiting) until the resource is free. After a successful lock, no
additional, i.e. recursive, locking attempts may be issued. |
epicsSpinTryLock() |
Similar to lock except that, if the resource is owned by another thread, the call completes
immediately. The return value is 0 if the resource is owned by the caller. |
epicsSpinUnlock() |
Release the spin lock resource which was locked by epicsSpinLock or epicsSpinTryLock.
The results are undefined if the lock is not held by the calling thread, or if epicsSpinUnlock
is used on an uninitialized spin lock. |
|
|
|
|
|
|
20.12.2 Implementation Notes
The default implementation uses POSIX spin locks on POSIX compliant systems, and epicsMutex for non-POSIX
environments.
20.13 epicsStdlib
epicsStdlib.h includes stdlib.h and epicsTypes.h and provides declarations for a series of string to number
conversion functions and macros.
20.13.1 Integer Parsing
These routines convert a string into an integer of the indicated type and number base. The units pointer argument may be
NULL, but if not it will be left pointing to the first non-whitespace character following the numeric string, or to the terminating
zero byte.
int epicsParseLong(const char ⋆str, long ⋆to, int base, char ⋆⋆units); int epicsParseULong(const char ⋆str, unsigned long ⋆to, int base, char ⋆⋆units); int epicsParseLLong(const char ⋆str, long long ⋆to, int base, char ⋆⋆units); int epicsParseULLong(const char ⋆str, unsigned long long ⋆to, int base, char ⋆⋆units); int epicsParseInt8(const char ⋆str, epicsInt8 ⋆to, int base, char ⋆⋆units); int epicsParseUInt8(const char ⋆str, epicsUInt8 ⋆to, int base, char ⋆⋆units); int epicsParseInt16(const char ⋆str, epicsInt16 ⋆to, int base, char ⋆⋆units); int epicsParseUInt16(const char ⋆str, epicsUInt16 ⋆to, int base, char ⋆⋆units); int epicsParseInt32(const char ⋆str, epicsInt32 ⋆to, int base, char ⋆⋆units); int epicsParseUInt32(const char ⋆str, epicsUInt32 ⋆to, int base, char ⋆⋆units); int epicsParseInt64(const char ⋆str, epicsInt64 ⋆to, int base, char ⋆⋆units); int epicsParseUInt64(const char ⋆str, epicsUInt64 ⋆to, int base, char ⋆⋆units);
The return value from these routines is a status code, zero meaning OK.
20.13.2 Floating-point Parsing
These routines convert a string into a floating-point type.
double epicsStrtod(const char ⋆str, char ⋆⋆endp); int epicsParseDouble(const char ⋆str, double ⋆to, char ⋆⋆units); int epicsParseFloat(const char ⋆str, float ⋆to, char ⋆⋆units); #define epicsParseFloat32(str, to, units) epicsParseFloat(str, to, units) #define epicsParseFloat64(str, to, units) epicsParseDouble(str, to, units)
epicsStrtod() has the same semantics as the C99 function strtod() and is provided because some
architectures do not fully conform to the standard. It is implemented as a simple macro on those architectures that do
conform.
epicsParseDouble and epicsParseFloat convert a string into a variable of the indicated type. The units pointer
argument may be NULL, but if not it will be left pointing to the first non-whitespace character following the numeric string, or
to the terminating zero byte.
The return value from these routines is a status code, zero meaning OK.
20.13.3 Replacements for scanf()
The following routines are implemented as macros that call routines described above. They return 1 for a successful conversion,
0 on failure, and can be used to replace equivalent calls to sscanf().
#define epicsScanLong(str, to, base) !epicsParseLong(str, to, base, NULL) #define epicsScanULong(str, to, base) !epicsParseULong(str, to, base, NULL) #define epicsScanLLong(str, to, base) !epicsParseLLong(str, to, base, NULL) #define epicsScanULLong(str, to, base) !epicsParseULLong(str, to, base, NULL) #define epicsScanFloat(str, to) !epicsParseFloat(str, to, NULL) #define epicsScanDouble(str, to) !epicsParseDouble(str, to, NULL)
epicsScanFloat and epicsScanDouble behave like sscanf with a "%f" and "%lf" format string, respectively.
They are provided because some architectures have implementations of scanf which do not accept NAN or
INFINITY.
20.14 epicsStdio
The epicsStdio.h first includes the operating systems’s stdio.h header, then provides definitions for the following
functions:
int epicsSnprintf(char ⋆str, size_t size, const char ⋆format, ...); int epicsVsnprintf(char ⋆str, size_t size, const char ⋆format, va_list ap); enum TF_RETURN {TF_OK = 0, TF_ERROR = 1}; enum TF_RETURN truncateFile(const char ⋆pFileName, unsigned size ); /⋆ Stream redirection of standard streams ⋆/ #define stdin epicsGetStdin() #define stdout epicsGetStdout() #define stderr epicsGetStderr() #define printf epicsStdoutPrintf #define puts epicsStdoutPuts #define putchar epicsStdoutPutchar FILE ⋆ epicsGetStdin(void); FILE ⋆ epicsGetStdout(void); FILE ⋆ epicsGetStderr(void); FILE ⋆ epicsGetThreadStdin(void); FILE ⋆ epicsGetThreadStdout(void); FILE ⋆ epicsGetThreadStderr(void); void epicsSetThreadStdin(FILE ⋆); void epicsSetThreadStdout(FILE ⋆); void epicsSetThreadStderr(FILE ⋆); int epicsStdoutPrintf(const char ⋆pformat, ...); int epicsStdoutPuts(const char ⋆str); int epicsStdoutPutchar(int c);
epicsSnprintf and epicsVsnprintf are meant to have the same semantics as the C99 functions snprintf and
vsnprintf. They are provided because some architectures do not implement these functions, while others implement them
incorrectly. Standardized as a C99 function, snprintf acts like sprintf except that the size argument gives the
maximum number of characters (including the trailing zero byte) that may be placed in str. Similarly vsnprintf is a
size-limited version of vsprintf. In both cases the return values are supposed to be the number characters (not counting the
terminating zero byte) that would be written to str if it was large enough to hold them all; the output has been truncated if the
return value is size or more.
On some operating systems though the implementations of these functions do not always return the correct value. If the OS
implementation does not correctly return the number of characters that would have been written when the output gets truncated,
it is not worth trying to fix this as long as they return size-1 instead; the resulting string must always be correctly terminated
with a zero byte.
On operating systems such as Solaris which follow the Single Unix Specification V2, the epicsSnprintf and
epicsVsnprintf implementations may not provide correct C99 semantics for the return value when size is given as zero.
On these systems epicsSnprintf and epicsVsnprintf can return an error (a value less than zero) when a
buffer length of zero is passed in, so callers should not use that technique to calculate the length of the buffer
required.
truncateFile returns TF_OK if the file is less than size bytes or if it was successfully truncated. Returns TF_ERROR if the
file could not be truncated.
The epicsSetThreadStdin/Stdout/Stderr routines allow the standard file steams to be redirected on a per
thread basis, e.g. calling epicsSetThreadStdout will affect only the thread which calls it. To cancel a
stream redirection, pass a NULL argument in another call to the same redirection routine that was used to set
it.
The routines epicsGetStdin/Stdout/Stderr and epicsStdoutPrintf/Puts/Putchar are not
normally named directly in user code. They are provided for the following macros that redefine the well-known C
identifiers:
- stdin becomes epicsGetStdin()
- stdout becomes epicsGetStdout()
- stderr becomes epicsGetStderr()
- printf becomes epicsStdoutPrintf
- puts becomes epicsStdoutPuts
- putchar becomes epicsStdoutPutchar
This is done so that any I/O through these standard streams can be redirected, usually to or from a file. The primary use of this
facility is iocsh, which allows redirection of the input and/or output streams when running commands. In order for the
redirection to work, all modules involved in I/O must include epicsStdio.h instead of the system header
stdio.h.
20.15 epicsTempFile
epicsTempFile.h provides definitions for the following functions:
void epicsTempName(char ⋆pbuf, size_t buflen); FILE ⋆ epicsTempFile(void);
epicsTempName and epicsTempFile can be called to get unique filenames and open FILE ⋆ pointers. Note that
epicsTempName cannot guarantee that the filenames it returns will not be created by some other thread or process after it has
returned, although it does check that the filename it generates does not already exist. This security hole is why POSIX.1-2008
marked tempnam() as obsolete. The epicsTempName function will probably be deprecated in a future release of
Base.
20.16 epicsThread
epicsThread.h contains C++ and C descriptions for a thread.
20.16.1 C Interface
typedef void (⋆EPICSTHREADFUNC)(void ⋆parm); #define epicsThreadPriorityMax 99 #define epicsThreadPriorityMin 0 /⋆ some generic values ⋆/ #define epicsThreadPriorityLow 10 #define epicsThreadPriorityMedium 50 #define epicsThreadPriorityHigh 90 /⋆ some iocCore specific values ⋆/ #define epicsThreadPriorityCAServerLow 20 #define epicsThreadPriorityCAServerHigh 40 #define epicsThreadPriorityScanLow 60 #define epicsThreadPriorityScanHigh 70 #define epicsThreadPriorityIocsh 91 #define epicsThreadPriorityBaseMax 91 /⋆ stack sizes for each stackSizeClass are implementation and CPU dependent ⋆/ typedef enum { epicsThreadStackSmall, epicsThreadStackMedium, epicsThreadStackBig } epicsThreadStackSizeClass; typedef enum { epicsThreadBooleanStatusFail, epicsThreadBooleanStatusSuccess } epicsThreadBooleanStatus; unsigned int epicsThreadGetStackSize(epicsThreadStackSizeClass size); /⋆ (epicsThreadId)0 is guaranteed to be an invalid thread id ⋆/ typedef struct epicsThreadOSD ⋆epicsThreadId; typedef int epicsThreadOnceId; #define EPICS_THREAD_ONCE_INIT 0 void epicsThreadOnce(epicsThreadOnceId ⋆id, EPICSTHREADFUNC, void ⋆arg); void epicsThreadExitMain(void); epicsThreadId epicsThreadCreate(const char ⋆name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void ⋆parm); void epicsThreadSuspendSelf(void); void epicsThreadResume(epicsThreadId id); unsigned int epicsThreadGetPriority(epicsThreadId id); unsigned int epicsThreadGetPrioritySelf(void); void epicsThreadSetPriority(epicsThreadId id, unsigned int priority); epicsThreadBooleanStatus epicsThreadHighestPriorityLevelBelow ( unsigned int priority, unsigned ⋆pPriorityJustBelow); epicsThreadBooleanStatus epicsThreadLowestPriorityLevelAbove ( unsigned int priority, unsigned ⋆pPriorityJustAbove); int epicsThreadIsEqual(epicsThreadId id1, epicsThreadId id2); int epicsThreadIsSuspended(epicsThreadId id); void epicsThreadSleep(double seconds); double epicsThreadSleepQuantum(void); epicsThreadId epicsThreadGetIdSelf(void); epicsThreadId epicsThreadGetId(const char ⋆name); int epicsThreadGetCPUs(void); const char ⋆ epicsThreadGetNameSelf(void); void epicsThreadGetName(epicsThreadId id, char ⋆name, size_t size); int epicsThreadIsOkToBlock(void); void epicsThreadSetOkToBlock(int isOkToBlock); void epicsThreadShowAll(unsigned int level); void epicsThreadShow(epicsThreadId id, unsigned int level); typedef void (⋆EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id); int epicsThreadHookAdd(EPICS_THREAD_HOOK_ROUTINE hook); int epicsThreadHookDelete(EPICS_THREAD_HOOK_ROUTINE hook); void epicsThreadHooksShow(void); void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func); typedef void ⋆ epicsThreadPrivateId; epicsThreadPrivateId epicsThreadPrivateCreate(void); void epicsThreadPrivateDelete(epicsThreadPrivateId id); void epicsThreadPrivateSet(epicsThreadPrivateId,void ⋆); void ⋆ epicsThreadPrivateGet(epicsThreadPrivateId);
Routine |
Meaning |
|
|
epicsThreadGetStackSize |
Get a stack size value that can be given to epicsThreadCreate. The
size argument should be one of the values epicsThreadStackSmall,
epicsThreadStackMedium or epicsThreadStackBig. |
epicsThreadOnce |
This is used as follows:
void myInitFunc(void ⋆ arg) { ... } epicsThreadOnceId onceFlag = EPICS_THREAD_ONCE_INIT; ... epicsThreadOnce(&onceFlag, myInitFunc, (void ⋆)myParm);
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 returns. Note that myInitFunc must not
call epicsThreadOnce with the same onceId. |
epicsThreadExitMain |
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. |
epicsThreadCreate |
Create a new thread. The use made of the priority, and stackSize
arguments is implementation dependent. Some implementations may
ignore one or other of these, but for portability appropriate values should
be given for both. The value passed as the stackSize parameter should
be obtained by calling epicsThreadGetStackSize. The funptr argument
specifies a function that implements the thread, and parm is the single
argument passed to funptr. A thread terminates when funptr returns. |
epicsThreadSuspendSelf |
This causes the calling thread to suspend. The only way it can resume is
for another thread to call epicsThreadResume. |
epicsThreadResume |
Resume a suspended thread. Only do this if you know that it is safe to
resume a suspended thread. |
epicsThreadGetPriority |
Get the priority of the specified thread. |
epicsThreadGetPrioritySelf |
Get the priority of this thread. |
epicsThreadSetPriority |
Set a new priority for the specified thread. The result is implementation
dependent. |
epicsThreadHighestPriorityLevelBelow |
Get a priority that is just lower than the specified priority. |
epicsThreadLowestPriorityLevelAbove |
Get a priority that is just above the specified priority. |
epicsThreadIsEqual |
Compares two threadIds and returns (0,1) if they (are not, are) the same. |
epicsThreadIsSuspended |
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. |
epicsThreadSleep |
Sleep for the specified period of time, i.e. sleep without using the cpu. If
delay is >0 then the thread will sleep at least until the next clock tick.
The exact time is determined by the underlying architecture. If delay is
<= 0 then a delay of 0 is requested of the underlying architecture. What
happens is architecture dependent but often it allows other threads of the
same priority to run. |
epicsThreadSleepQuantum |
This function returns the minimum slumber interval obtainable with
epicsThreadSleep() in seconds. On most OS there is a system scheduler
interrupt interval which determines the value of this parameter.
Knowledge of this parameter is used by the various components of
EPICS to improve scheduling of software tasks intime when the
reduction of average time scheduling errors is important. If this
parameter is unknown or is unpredictable for a particular OS then it is
safe to return zero. |
epicsThreadGetIdSelf |
Get the threadId of the calling thread. |
epicsThreadGetId |
Get the threadId of the specified thread. A return value of 0 means that
no thread was found with the specified name. |
epicsThreadGetCPUs |
Get the number of CPUs (logical cores) available to the IOC. On systems
that provide Hyper-Threading, this may be more the number of physical
CPU cores. |
epicsThreadGetNameSelf |
Get the name of the calling thread. |
|
|
epicsThreadGetName |
Get the name of the specified thread. The value is copied to a caller
specified buffer so that if the thread terminates the caller is not left with
a pointer to something that may no longer exist. |
epicsThreadIsOkToBlock |
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. |
epicsThreadSetOkToBlock |
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. |
epicsThreadShowAll |
Display info about all threads. |
epicsThreadShow |
Display info about the specified thread. |
epicsThreadHookAdd |
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. |
epicsThreadHookDelete |
Remove routine from the list of hooks run at thread creation time. |
epicsThreadHooksShow |
Print the current list of hook function pointers. |
epicsThreadMap |
Call func once for every known thread. |
epicsThreadPrivateCreate |
Thread private variables are intended for use by legacy libraries written
for a single threaded environment and which used a global variable
to store private data. The only code in base that currently needs
this facility is channel access. A library that needs a private variable
should make exactly one call to epicsThreadPrivateCreate and store the
index returned. Each thread can later call epicsThreadPrivateGet and
epicsThreadPrivateSet with that index to access a thread-specific pointer
store. |
epicsThreadPrivateDelete |
Delete a thread private variable. |
epicsThreadPrivateSet |
Set the value for a thread private pointer. |
epicsThreadPrivateGet |
Get the value of a thread private pointer. The value returned is the last
value given to epicsThreadPrivateSet by the same thread. If called before
epicsThreadPrivateSet the pointer’s value is NULL. |
|
|
|
|
|
The epicsThread API is meant as a somewhat minimal interface for multithreaded applications. It can be implemented on 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.
20.16.2 C++ Interface
class epicsThreadRunable { public: virtual void run() = 0; virtual void stop(); virtual void show(unsigned int level) const; }; class epicsShareClass epicsThread { public: epicsThread (epicsThreadRunable &,const char ⋆name, unsigned int stackSize, unsigned int priority=epicsThreadPriorityLow); virtual ~epicsThread (); void start(); void exitWait (); bool exitWait (const double delay ); void exitWaitRelease (); // noop if not called by managed thread static void exit (); void resume (); void getName (char ⋆name, size_t size) const; epicsThreadId getId () const; unsigned int getPriority () const; void setPriority (unsigned int); bool priorityIsEqual (const epicsThread &otherThread) const; bool isSuspended () const; bool isCurrentThread () const; bool operator == (const epicsThread &rhs) const; /⋆ these operate on the current thread ⋆/ static void suspendSelf (); static void sleep (double seconds); static epicsThread & getSelf (); static const char ⋆ getNameSelf (); static bool isOkToBlock (); static void setOkToBlock(bool isOkToBlock) ; private: ... }; template <class T> class epicsThreadPrivate { public: epicsThreadPrivate (); ~epicsThreadPrivate (); T ⋆get () const; void set (T ⋆); class unableToCreateThreadPrivate {}; // exception private: ... };
The C++ interface is a wrapper around the C interface. Two differences are the method start and the class
epicsThreadRunable.
The start method must not be called until after the epicsThread constructor has returned. Calling the start
method allows the run method of the epicsThreadRunable object to be executed in the context of the new
thread.
Code using the C++ API must provide a class that derives from epicsThreadRunable. For example:
class myThread: public epicsThreadRunable { public: myThread(int arg,const char ⋆name); virtual ~myThread(); virtual void run(); epicsThread thread; } myThread::myThread(int arg,const char ⋆name) : thread(⋆this,name,epicsThreadGetStackSize(epicsThreadStackSmall),50) { thread.start(); } myThread::~myThread() {} void myThread::run() { // ... }
20.17 epicsTime
epicsTime.h contains C++ and C descriptions for time.
20.17.1 Time Related Structures
/⋆ epics time stamp for C interface⋆/ typedef struct epicsTimeStamp { epicsUInt32 secPastEpoch; /⋆ seconds since 0000 Jan 1, 1990 ⋆/ epicsUInt32 nsec; /⋆ nanoseconds within second ⋆/ } epicsTimeStamp; /⋆TS_STAMP is deprecated ⋆/ #define TS_STAMP epicsTimeStamp struct timespec; /⋆ POSIX real time ⋆/ struct timeval; /⋆ BSD ⋆/ struct l_fp; /⋆ NTP timestamp ⋆/ // extend ANSI C RTL "struct tm" to include nano seconds within a second // and a struct tm that is adjusted for the local timezone struct local_tm_nano_sec { struct tm ansi_tm; /⋆ ANSI C time details ⋆/ unsigned long nSec; /⋆ nano seconds extension ⋆/ }; // extend ANSI C RTL "struct tm" to includes nano seconds within a second // and a struct tm that is adjusted for GMT (UTC) struct gm_tm_nano_sec { struct tm ansi_tm; /⋆ ANSI C time details ⋆/ unsigned long nSec; /⋆ nano seconds extension ⋆/ }; // wrapping this in a struct allows conversion to and // from ANSI time_t but does not allow unexpected // conversions to occur struct time_t_wrapper { time_t ts; };
The above structures are for the various time formats.
NOTE on conversion. The epics implementation will properly convert between the various formats from the beginning of the
EPICS epoch until at least 2038. Unless the underlying architecture support has defective POSIX, BSD/SRV5, or standard C
time support the epics implementation should be valid until 2106.
20.17.2 C++ Interface
class epicsTime; class epicsTimeEvent { public: epicsTimeEvent (const int &number); operator int () const; private: int eventNumber; }; class epicsTime { public: // exceptions class unableToFetchCurrentTime {}; class formatProblemWithStructTM {}; epicsTime (); epicsTime (const epicsTime &t); static epicsTime getEvent (const epicsTimeEvent &event); static epicsTime getCurrent (); // convert to and from EPICS epicsTimeStamp format operator epicsTimeStamp () const; epicsTime (const epicsTimeStamp &ts); epicsTime & operator = (const epicsTimeStamp &rhs); // convert to and from ANSI time_t operator time_t_wrapper () const; epicsTime (const time_t_wrapper &tv); epicsTime & operator = (const time_t_wrapper &rhs); // convert to and from ANSI Cs "struct tm" (with nano seconds) // adjusted for the local time zone operator local_tm_nano_sec () const; epicsTime (const local_tm_nano_sec &ts); epicsTime & operator = (const local_tm_nano_sec &rhs); // convert to and from ANSI Cs "struct tm" (with nano seconds) // adjusted for GM time (UTC) operator gm_tm_nano_sec () const; epicsTime ( const gm_tm_nano_sec & ); epicsTime & operator = ( const gm_tm_nano_sec & ); // convert to and from POSIX RT's "struct timespec" operator struct timespec () const; epicsTime (const struct timespec &ts); epicsTime & operator = (const struct timespec &rhs); // convert to and from BSD's "struct timeval" operator struct timeval () const; epicsTime (const struct timeval &ts); epicsTime & operator = (const struct timeval &rhs); // convert to and from NTP timestamp format operator l_fp () const; epicsTime (const l_fp &); epicsTime & operator = (const l_fp &rhs); // convert to and from WIN32s FILETIME (implemented only on WIN32) operator struct _FILETIME () const; epicsTime ( const struct _FILETIME & ); epicsTime & operator = ( const struct _FILETIME & ); // arithmetic operators double operator- (const epicsTime &rhs) const; // returns seconds epicsTime operator+ (const double &rhs) const; // add rhs seconds epicsTime operator- (const double &rhs) const; // subtract rhs seconds epicsTime operator+= (const double &rhs); // add rhs seconds epicsTime operator-= (const double &rhs); // subtract rhs seconds // comparison operators bool operator == (const epicsTime &rhs) const; bool operator != (const epicsTime &rhs) const; bool operator <= (const epicsTime &rhs) const; bool operator < (const epicsTime &rhs) const; bool operator >= (const epicsTime &rhs) const; bool operator > (const epicsTime &rhs) const; // convert current state to user-specified string size_t strftime (char ⋆pBuff, size_t bufLength, const char ⋆pFormat) const; // dump current state to standard out void show (unsigned interestLevel) const; private: ... };
20.17.3 class epicsTimeEvent
class epicsShareClass epicsTimeEvent { public: epicsTimeEvent (const int &number); operator int () const; private: int eventNumber; };
Method |
Meaning |
|
|
Convert to/from integer |
Does not currently check that the range of the integer is valid, although it might one day. |
|
|
|
|
|
20.17.4 class epicsTime
epicsTime Method |
Meaning |
|
|
|
|
|
epicsTime() |
The default constructor sets the time to the beginning of the epics epoch. |
epicsTime(const epicsTime &t) |
Copy constructor, copies the time from its argument. |
static getEvent |
Returns an epicsTime indicating when the associated event last occurred. See the
description of the C routine epicsTimeGetEvent below for details. |
static getCurrent |
Returns an epicsTime containing the current time. For example: epicsTime now = epicsTime::getCurrent(); |
convert to/from epicsTimeStamp |
Three epicsTime methods interface with epicsTimeStamp values: A constructor, an
assignment operator, and a conversion operator. For example: epicsTimeStamp ts1 = {12345, 67890}, ts2; epicsTime t1(ts1), t2; // constructor t2 = ts1; // assignment ts2 = t1; // conversion operator |
convert to/from time_t |
The structure time_t_wrapper is used instead of time_t directly to avoid undesired
conversions to integer types. Three methods are provided for ANSI time_t: A
constructor, an assignment operator, and a conversion operator. Assume the following
definitions: time_t tt; time_t_wrapper ttw; epicsTime time; An example of the copy constructor is: ttw.ts = tt; epicsTime time1(ttw); An example of the assignment operator is: time = ttw; An example of the time_t_wrapper operator is: ttw = time; tt = ttw.ts; |
convert to/from struct tm in local
timezone |
The structure local_tm_nano_sec is used instead of struct tm directly to add a
nanoseconds field and indicate the time is expressed in the local timezone. Three
methods are provided for local_tm_nano_sec: A constructor, an assignment operator,
and a conversion operator. Assume the following definitions: local_tm_nano_sec ltn; epicsTime time; An example of the copy constructor is: epicsTime time1(ltn); An example of the assignment operator is: time = ltn; An example of the local_tm_nano_sec operator is: ltn = time; |
convert to/from struct tm in UTC |
The structure local_tm_nano_sec is used instead of struct tm directly to add a
nanoseconds field and indicate the time is expressed in UTC. Three methods
are provided for gm_tm_nano_sec: A constructor, an assignment operator, and a
conversion operator. Assume the following definitions: gm_tm_nano_sec gtn; epicsTime time; An example of the copy constructor is: epicsTime time1(gtn); An example of the assignment operator is: time = gtn; An example of the gm_tm_nano_sec operator is: gtn = time; |
convert to/from struct timespec |
Three methods are provided for the POSIX struct timespec: A constructor, an
assignment operator, and a conversion operator. Assume the following definitions: struct timespec tts; epicsTime time; An example of the copy constructor is: epicsTime time1(tts); An example of the assignment operator is: time = tts; An example of the conversion operator is: tts = time; |
convert to/from struct timeval |
Three methods are provided for BSD’s struct timeval: A constructor, an assignment
operator, and a conversion operator. Assume the following definitions: struct timeval ttv; epicsTime time; An example of the copy constructor is: epicsTime time1(ttv); An example of the assignment operator is: time = ttv; An example of the conversion operator is: ttv = time; |
convert to/from NTP timestamps |
Three methods are provided for the NTP timestamp structure: A constructor, an
assignment operator, and a conversion operator. Assume the following definitions: l_fp ntp; epicsTime time; An example of the copy constructor is: epicsTime time1(ntp); An example of the assignment operator is: time = ntp; An example of the conversion operator is: ntp = time; |
arithmetic operators -, +, +=, -= |
The arithmetic operators allow the difference of two epicsTimes, with the result in
seconds. It also allows -, +, +=, and -= where the left hand argument is an epicsTime
and the right hand argument is a double. Examples are: epicsTime time, time1, time2; double t1,t2,t3; ... t1 = time2 - time1; time = time1 + 4.5; time = time2 - t3; time2 += 6.0; |
Comparison operators ==, |=, <=,
<, >=, > |
Two epics times can be compared: epicsTime time1, time2; ... if (time1 <= time2) ... |
strftime |
This method is an extension of the standard C library routine strftime. See your OS
documentation for details about the standard routine. The epicsTime method adds
support for the printing the fractional portion of the time. It searches the format string
for the sequence %0nf where n is the desired precision, and uses this format to convert
the fractional seconds to the requested precision. For example: epicsTime time = epicsTime::getCurrent(); char buf[30]; time.strftime(buf, 30, "%Y-%m-%d %H:%M:%S.%06f"); printf("%s\n", buf); This will print the current time in the format: 2001-01-26 20:50:29.813505 |
show |
Shows the date/time. |
|
|
|
|
20.17.5 C Interface
/⋆ All epicsTime routines return (-1,0) for (failure,success) ⋆/ #define epicsTimeOK 0 #define epicsTimeERROR (-1) /⋆Some special values for eventNumber⋆/ #define epicsTimeEventCurrentTime 0 #define epicsTimeEventBestTime -1 #define epicsTimeEventDeviceTime -2 /⋆ These are implemented in the "generalTime" framework ⋆/ int epicsTimeGetCurrent (epicsTimeStamp ⋆pDest); int epicsTimeGetEvent (epicsTimeStamp ⋆pDest, int eventNumber); /⋆ These are callable from an Interrupt Service Routine ⋆/ int epicsTimeGetCurrentInt(epicsTimeStamp ⋆pDest); int epicsTimeGetEventInt(epicsTimeStamp ⋆pDest, int eventNumber); /⋆ convert to and from ANSI C's "time_t" ⋆/ int epicsTimeToTime_t (time_t ⋆pDest, const epicsTimeStamp ⋆pSrc); int epicsTimeFromTime_t (epicsTimeStamp ⋆pDest, time_t src); /⋆convert to and from ANSI C's "struct tm" with nano seconds ⋆/ int epicsTimeToTM (struct tm ⋆pDest, unsigned long ⋆pNSecDest, const epicsTimeStamp ⋆pSrc); int epicsTimeToGMTM (struct tm ⋆pDest, unsigned long ⋆pNSecDest, const epicsTimeStamp ⋆pSrc); int epicsTimeFromTM (epicsTimeStamp ⋆pDest, const struct tm ⋆pSrc, unsigned long nSecSrc); int epicsTimeFromGMTM (epicsTimeStamp ⋆pDest, const struct tm ⋆pSrc, unsigned long nSecSrc); /⋆ convert to and from POSIX RT's "struct timespec" ⋆/ int epicsTimeToTimespec (struct timespec ⋆pDest, const epicsTimeStamp ⋆pSrc); int epicsTimeFromTimespec (epicsTimeStamp ⋆pDest, const struct timespec ⋆pSrc); /⋆ convert to and from BSD's "struct timeval" ⋆/ int epicsTimeToTimeval (struct timeval ⋆pDest, const epicsTimeStamp ⋆pSrc); int epicsTimeFromTimeval (epicsTimeStamp ⋆pDest, const struct timeval ⋆pSrc); /⋆arithmetic operations ⋆/ double epicsTimeDiffInSeconds ( const epicsTimeStamp ⋆pLeft, const epicsTimeStamp ⋆pRight); void epicsTimeAddSeconds ( epicsTimeStamp ⋆pDest, double secondsToAdd); /⋆ adds seconds to ⋆pDest ⋆/ /⋆comparison operations: returns (0,1) if (false,true) ⋆/ int epicsTimeEqual(const epicsTimeStamp ⋆pLeft, const epicsTimeStamp ⋆pRight); int epicsTimeNotEqual(const epicsTimeStamp ⋆pLeft,const epicsTimeStamp ⋆pRight); int epicsTimeLessThan(const epicsTimeStamp ⋆pLeft,const epicsTimeStamp ⋆pRight); int epicsTimeLessThanEqual( const epicsTimeStamp ⋆pLeft, const epicsTimeStamp ⋆pRight); int epicsTimeGreaterThan ( const epicsTimeStamp ⋆pLeft, const epicsTimeStamp ⋆pRight); int epicsTimeGreaterThanEqual ( const epicsTimeStamp ⋆pLeft, const epicsTimeStamp ⋆pRight); /⋆convert to ASCII string ⋆/ size_t epicsTimeToStrftime ( char ⋆pBuff, size_t bufLength, const char ⋆pFormat, const epicsTimeStamp ⋆pTS); /⋆ dump current state to standard out ⋆/ void epicsTimeShow (const epicsTimeStamp ⋆, unsigned interestLevel); /⋆ OS dependent reentrant versions of the ANSI C interface because ⋆/ /⋆ vxWorks gmtime_r interface does not match POSIX standards ⋆/ int epicsTime_localtime ( const time_t ⋆clock, struct tm ⋆result ); int epicsTime_gmtime ( const time_t ⋆clock, struct tm ⋆result );
The C interface provides most of the features as the C++ interface. The features of the C++ operators are provided as
functions.
Note that the epicsTimeGetCurrent() and epicsTimeGetEvent() routines and their ISR-callable
equivalents epicsTimeGetCurrentInt() and epicsTimeGetEventInt() are now implemented in
epicsGeneralTime.c
20.18 osiPoolStatus
osiPoolStatus.h contains the following description:
int osiSufficentSpaceInPool(void);
Method |
Meaning |
|
|
osiSufficentSpaceInPool |
Return (true,false) if there is sufficient free memory. |
|
|
|
|
|
This determines if enough free memory exists to continue.
A vxWorks version returns (true,false) if memFindMax returns (>100000, <=100000) bytes.
The default version always returns true.
20.19 osiProcess
osiProcess.h contains the following:
typedef enum osiGetUserNameReturn { osiGetUserNameFail, osiGetUserNameSuccess }osiGetUserNameReturn; osiGetUserNameReturn osiGetUserName (char ⋆pBuf, unsigned bufSize); /⋆ ⋆ Spawn detached process with named executable, but return ⋆ osiSpawnDetachedProcessNoSupport if the local OS does not ⋆ support heavy weight processes. ⋆/ typedef enum osiSpawnDetachedProcessReturn { osiSpawnDetachedProcessFail, osiSpawnDetachedProcessSuccess, osiSpawnDetachedProcessNoSupport }osiSpawnDetachedProcessReturn; osiSpawnDetachedProcessReturn osiSpawnDetachedProcess( const char ⋆pProcessName, const char ⋆pBaseExecutableName);
Not otherwise documented.
20.20 Ignoring Posix Signals
epicsSignal.h contains the following commented declarations:
/⋆ ⋆ Required to avoid problems with soft IOCs getting SIGHUPs ⋆ when a Channel Access client disconnects: ⋆/ void epicsSignalInstallSigHupIgnore ( void ); /⋆ ⋆ Required to avoid terminating a process which is blocking ⋆ in a socket send() call when a SIGPIPE signal is generated ⋆ by the OS: ⋆/ void epicsSignalInstallSigPipeIgnore ( void ); /⋆ ⋆ Required only if shutdown() and close() do not interrupt ⋆ a thread blocking in a socket system call: ⋆/ void epicsSignalInstallSigAlarmIgnore ( void ); void epicsSignalRaiseSigAlarm ( struct epicsThreadOSD ⋆ );
Not otherwise documented.
20.21 OS-Independent Socket API
The header file osiSock.h provides wrappers around the different socket APIs provided by the supported operating systems.
This API was designed to make it possible to write network applications that will compile and run on any OS. See the
comments and declarations in the header file for details.
20.22 epicsMMIO
epicsMMIO.h provides a set of calls to perform safe access to Memory Mapped I/O regions. This is the typical means to
access VME or PCI bus devices.
The following are the equivalant signatures of the MMIO read and write calls. The actual implementations may use
macros.
epicsUInt8 ioread8 (void⋆ addr); epicsUInt16 nat_ioread16(void⋆ addr); epicsUInt16 be_ioread16(void⋆ addr); epicsUInt16 le_ioread16(void⋆ addr); epicsUInt32 nat_ioread32(void⋆ addr); epicsUInt32 be_ioread32(void⋆ addr); epicsUInt32 le_ioread32(void⋆ addr); void iowrite8 (void⋆ addr, epicsUInt8 val); void nat_iowrite16(void⋆ addr, epicsUInt16 val); void be_iowrite16(void⋆ addr, epicsUInt16 val); void le_iowrite16(void⋆ addr, epicsUInt16 val); void nat_iowrite32(void⋆ addr, epicsUInt32 val); void be_iowrite32(void⋆ addr, epicsUInt32 val); void le_iowrite32(void⋆ addr, epicsUInt32 val);
The 16 and 32-bit calls have three variants: nat_, be_, and le_ which specify the byte ordering of the MMIO register being
access as having: CPU Native, Big Endian, or Little Endian byte order. The specification will be used to re-order the bytes
read/written into the CPU native integer format.
Determining which of these variants to use in a specific case requires knowledge of the underlying hardware (bus and/or
device). This document can present only a general rule, which is that the nat_ variant will be used for VME devices as the
common bus bridges do automatic byte lane swapping. PCI devices will generally use of one be_ or le_, although some
devices have been known to have a mix of BE and LE registers.
These calls do not perform any checking of address alignment.
All of these calls have CPU, OS, and/or compiler specific definitions which try to preserve all MMIO operations by defeating
instruction reordering and operation splitting/combining optimizations by the compiler and CPU.
20.23 Device Support Library
NOTE: EPICS Base only provides vxWorks and RTEMS back-end implementations of these routines. Versions of the back-end
routines for other operating systems can be added in a support or IOC application.
20.23.1 Overview
devLib.h provides definitions for a library of routines useful for device and driver modules, which are primarily indended for
accessing VME devices. If all VME drivers register with these routines then addressing conflicts caused by multiple
device/drivers trying to use the same VME addresses will be detected.
20.23.2 Location Probing
20.23.2.1 Read Probe
long devReadProbe( unsigned wordSize, volatile const void ⋆ptr, void ⋆pValueRead);
Performs a bus-error-safe atomic read operation width wordSize bytes from the ptr location, placing the value read (if
successful) at pValueRead. The routine returns a failure status (non-zero) if a bus error occurred during the read
cycle.
20.23.2.2 Write Probe
long devWriteProbe( unsigned wordSize, volatile void ⋆ptr, const void ⋆pValueWritten);
Performs a bus-error-safe atomic write operation width wordSize which copies the value from pValueWritten to the
ptr location. The routine returns a failure status (non-zero) if a bus error occurred during the write cycle.
20.23.2.3 No Response Probe
long devNoResponseProbe( epicsAddressType addrType, size_t base, size_t size);
This routine performs a series of read probes for all word sizes from char to long at every naturally aligned location in the range
[base, base+size) for the given bus address type. It returns an error if any location responds or if any such location cannot
be mapped.
20.23.3 Registering VME Addresses
20.23.3.1 Definitions of Address Types
typedef enum { atVMEA16, atVMEA24, atVMEA32, atISA, atVMECSR, atLast /⋆ atLast is the last enum in this list ⋆/ } epicsAddressType; char ⋆epicsAddressTypeName[] = { "VME␣A16", "VME␣A24", "VME␣A32", "ISA", "VME␣CSR" };
20.23.3.2 Register Address
long devRegisterAddress( const char ⋆pOwnerName, epicsAddressType addrType, size_t logicalBaseAddress, size_t size, /⋆ bytes ⋆/ volatile void ⋆⋆pLocalAddress);
This routine is called to register a VME address. The routine keeps a list of all VME address ranges requested and returns an
error message if an attempt is made to register any addresses that overlap a range that is already being used.
⋆pLocalAddress is set equal to the address as seen by the caller.
20.23.3.3 Print Address Map
This routine displays the table of registered VME address ranges, including the owner of each registered address.
20.23.3.4 Unregister Address
long devUnregisterAddress( epicsAddressType addrType, size_t logicalBaseAddress, const char ⋆pOwnerName);
This routine releases address ranges previously registered by a call to devRegisterAddress or devAllocAddress.
20.23.3.5 Allocate Address
long devAllocAddress( const char ⋆pOwnerName, epicsAddressType addrType, size_t size, unsigned alignment, /⋆number of low zero bits needed in addr⋆/ volatile void ⋆⋆pLocalAddress);
This routine is called to request the library to allocate an address block of a particular address type. This is useful for devices
that appear in more than one address space and can program the base address of one window using registers found in another
window.
20.23.4 Interrupt Connection Routines
20.23.4.1 Connect
long devConnectInterruptVME( unsigned vectorNumber, void (⋆pFunction)(void ⋆), void ⋆parameter);
Connect ISR pFunction up to the VME interrupt vectorNumber.
20.23.4.2 Disconnect
long devDisconnectInterruptVME( unsigned vectorNumber, void (⋆pFunction)(void ⋆));
Disconnects an ISR from its VME interrupt vector. The parameter pFunction should be set to the C function pointer that was
connected. It is used as a key to prevent a driver from inadvertently removing an interrupt handler that it didn’t
install.
20.23.4.3 Check If Used
int devInterruptInUseVME( unsigned vectorNumber);
Determines if a VME interrupt vector is in use, returning a boolean value.
20.23.4.4 Enable
long devEnableInterruptLevelVME( unsigned level);
Enable the given VME interrupt level onto the CPU.
20.23.4.5 Disable
long devDisableInterruptLevelVME( unsigned level);
Disable VME interrupt level. This routine should generally never be used, since it is impossible for a driver to know whether
any other active drivers are still making use of a particular interrupt level.
20.23.5 Macros for Normalized Analog Values
20.23.5.1 Convert Digital Value to a Normalized Double Value
#define devCreateMask(NBITS)((1<<(NBITS))-1) #define devDigToNml(DIGITAL,NBITS) \ (((double)(DIGITAL))/devCreateMask(NBITS))
20.23.5.2 Convert Normalized Double Value to a Digital Value
#define devNmlToDig(NORMAL,NBITS) \ (((long)(NORMAL)) ⋆ devCreateMask(NBITS))
20.23.6 Deprecated Interrupt Routines
20.23.6.1 Definitions of Interrupt Types (deprecated)
typedef enum {intCPU, intVME, intVXI} epicsInterruptType;
The routines that use this typedef have all been deprecated, and currently only exist for backwards compatibility purposes. The
typedef will be removed in a future release, along with those routines.
20.23.6.2 Connect (deprecated)
long devConnectInterrupt( epicsInterruptType intType, unsigned vectorNumber, void (⋆pFunction)(), void ⋆parameter);
This routine has been deprecated, and currently only exists for backwards compatibility purposes. Uses of this routine should
be converted to call devConnectInterruptVME or related routines instead. This routine will be removed in a future
release.
20.23.6.3 Disconnect (deprecated)
long devDisconnectInterrupt( epicsInterruptType intType, unsigned vectorNumber);
This routine has been deprecated, and currently only exists for backwards compatibility purposes. Uses of this routine should
be converted to call devDisconnectInterruptVME or related routines instead. This routine will be removed in a future
release.
20.23.6.4 Enable Level (deprecated)
long devEnableInterruptLevel( epicsInterruptType intType, unsigned level);
This routine has been deprecated, and currently only exists for backwards compatibility purposes. Uses of this routine should
be converted to call devEnableInterruptLevelVME or related routines instead. This routine will be removed in a future
release.
20.23.6.5 Disable Level (deprecated)
long devDisableInterruptLevel( epicsInterruptType intType, unsigned level);
This routine has been deprecated, and currently only exists for backwards compatibility purposes. Uses of this routine should
be converted to call devDisableInterruptLevelVME or related routines instead. This routine will be removed in a
future release.
20.24 vxWorks Specific routines and Headers
The routines described in this section are included in a application by the Makfile command:
<appl>_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
20.24.1 veclist
This routine shows the vxWorks interrupt vector table, but only works properly on 68K family CPUs.
20.24.2 logMsgToErrlog
This traps all calls to logMsg and sends them to errlogPrintf.
20.24.3 camacLib.h
This was included with 3.13.
20.24.4 epicsDynLink
This provides the routines symFindByNameEPICS and symFindByNameAndTypeEPICS. It is only provided for
modules that have not been converted to use epicsFindSymbol. These routines are deprecated.
20.24.5 module_types.h
This is only provided for device/driver support that have not been converted to use OSI features of base. This header is
deprecated. Instead of using this, drivers should register a configuration command to obtain the information originally provided
by module_types.h
20.24.6 task_params.h
This is only provided for device/driver support that have not been converted to use OSI features of base. This header is
deprecated.
20.24.7 vxComLibrary
This routine causes epicsDynLink, logMsgToErrlog and veclist to be loaded.