Merge remote-tracking branch 'github/7.0' into 7.0

* github/7.0:
  Unify doxygen keywords to use '\' not '@'
  Applied all doxy-libcom changes to latest headers

# Conflicts:
#	modules/libcom/src/yajl/yajl_common.h
This commit is contained in:
Michael Davidsaver
2020-05-20 13:33:36 -07:00
43 changed files with 3791 additions and 994 deletions

View File

@@ -6,8 +6,15 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*asTrapWrite.h*/
/* Author: Marty Kraimer Date: 07NOV2000 */
/**
* \file asTrapWrite.h
* \brief API for monitoring external put operations to an IOC.
* \author Marty Kraimer
*
* The access security subsystem provides an API asTrapWrite that makes
* put/write requests visible to any facility that registers a listener.
*/
#ifndef INCasTrapWriteh
#define INCasTrapWriteh
@@ -18,37 +25,68 @@
extern "C" {
#endif
/**
* \brief The message passed to registered listeners.
*/
typedef struct asTrapWriteMessage {
const char *userid;
const char *hostid;
const char *userid; /**< \brief Userid of whoever orginated the request. */
const char *hostid; /**< \brief Hostid of whoever orginated the request. */
/** \brief A field for use by the server.
*
* Any listener that uses this field must know what type of
* server is forwarding the put requests. This pointer holds
* the value the server provides to asTrapWriteWithData(), which
* for RSRV is the dbChannel pointer for the target field.
*/
void *serverSpecific;
/** \brief A field for use by the \ref asTrapWriteListener.
*
* When the listener is called before the write, this has the
* value 0. The listener can give it any value it desires
* and it will have the same value when the listener gets
* called again after the write.
*/
void *userPvt;
int dbrType; /* Data type from ca/db_access.h, NOT dbFldTypes.h */
int no_elements;
void *data; /* Might be NULL if no data is available */
int dbrType; /**< \brief Data type from ca/db_access.h, NOT dbFldTypes.h */
int no_elements; /**< \brief Array length */
void *data; /**< \brief Might be NULL if no data is available */
} asTrapWriteMessage;
/**
* \brief An identifier needed to unregister an listener.
*/
typedef void *asTrapWriteId;
/**
* \brief Pointer to a listener function.
*
* Each registered listener function is called twice for every put; once
* before and once after the write is performed.
* The listener may set \c userPvt in the first call and retrieve it in the
* second call.
*
* Each asTrapWriteMessage can change or may be deleted after the user's
* asTrapWriteListener returns
*
* The listener function is called by a server thread so it must not block
* or do anything that causes a delay.
*/
typedef void(*asTrapWriteListener)(asTrapWriteMessage *pmessage,int after);
/**
* \brief Register function to be called on asTrapWriteListener.
* \param func The listener function to be called.
* \return A listener identifier for unregistering this listener.
*/
epicsShareFunc asTrapWriteId epicsShareAPI asTrapWriteRegisterListener(
asTrapWriteListener func);
/**
* \brief Unregister asTrapWriteListener.
* \param id Listener identifier from asTrapWriteRegisterListener().
*/
epicsShareFunc void epicsShareAPI asTrapWriteUnregisterListener(
asTrapWriteId id);
/*
* asTrapWriteListener is called before and after the write is performed.
* The listener can set userPvt on the before call and retrieve it after
* after = (0,1) (before,after) the put.
*
* Each asTrapWriteMessage can change or may be deleted after
* the user's asTrapWriteListener returns
*
* asTrapWriteListener delays the associated server thread so it must not
* do anything that causes to to block.
*/
#ifdef __cplusplus
}
#endif

View File

@@ -4,16 +4,19 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 9-93
/**
* \file bucketLib.h
* \author Jeffrey O. Hill
* \brief A hash table. Do not use for new code.
*
* NOTES:
* .01 Storage for identifier must persist until an item is deleted
* \details
* A hash table for which keys may be unsigned integers, pointers, or
* strings. This API is used by the IOC's Channel Access Server, but
* it should not be used by other code.
*
* \note Storage for identifiers must persist until an item is deleted
*/
#ifndef INCbucketLibh
@@ -27,10 +30,13 @@ extern "C" {
#include "epicsTypes.h"
#include "shareLib.h"
/** \brief Internal: bucket identifier */
typedef unsigned BUCKETID;
/** \brief Internal: bucket key type */
typedef enum {bidtUnsigned, bidtPointer, bidtString} buckTypeOfId;
/** \brief Internal: bucket item structure */
typedef struct item{
struct item *pItem;
const void *pId;
@@ -38,6 +44,7 @@ typedef struct item{
buckTypeOfId type;
}ITEM;
/** \brief Internal: Hash table structure */
typedef struct bucket{
ITEM **pTable;
void *freeListPVT;
@@ -45,47 +52,147 @@ typedef struct bucket{
unsigned hashIdNBits;
unsigned nInUse;
}BUCKET;
epicsShareFunc BUCKET * epicsShareAPI bucketCreate (unsigned nHashTableEntries);
epicsShareFunc int epicsShareAPI bucketFree (BUCKET *prb);
epicsShareFunc int epicsShareAPI bucketShow (BUCKET *pb);
/*
* !! Identifier must exist (and remain constant) at the specified address until
* the item is deleted from the bucket !!
/**
* \brief Creates a new hash table
* \param nHashTableEntries Table size
* \return Pointer to the newly created hash table, or NULL.
*/
epicsShareFunc int epicsShareAPI bucketAddItemUnsignedId (BUCKET *prb,
epicsShareFunc BUCKET * epicsShareAPI bucketCreate (unsigned nHashTableEntries);
/**
* \brief Release memory used by a hash table
* \param *prb Pointer to the hash table
* \return S_bucket_success
* \note All items must be deleted from the hash table before calling this.
*/
epicsShareFunc int epicsShareAPI bucketFree (BUCKET *prb);
/**
* \brief Display information about a hash table
* \param *prb Pointer to the hash table
* \return S_bucket_success
*/
epicsShareFunc int epicsShareAPI bucketShow (BUCKET *prb);
/**
* \brief Add an item identified by an unsigned int to the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \param *pApp Pointer to the payload
* \return Status value
*/
epicsShareFunc int epicsShareAPI bucketAddItemUnsignedId (BUCKET *prb,
const unsigned *pId, const void *pApp);
epicsShareFunc int epicsShareAPI bucketAddItemPointerId (BUCKET *prb,
/**
* \brief Add an item identified by a pointer to the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \param *pApp Pointer to the payload
* \return Status value
*/
epicsShareFunc int epicsShareAPI bucketAddItemPointerId (BUCKET *prb,
void * const *pId, const void *pApp);
epicsShareFunc int epicsShareAPI bucketAddItemStringId (BUCKET *prb,
/**
* \brief Add an item identified by a string to the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \param *pApp Pointer to the payload
* \return Status value
*/
epicsShareFunc int epicsShareAPI bucketAddItemStringId (BUCKET *prb,
const char *pId, const void *pApp);
/**
* \brief Remove an item identified by a string from the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Status value
*/
epicsShareFunc int epicsShareAPI bucketRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId);
/**
* \brief Remove an item identified by a pointer from the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Status value
*/
epicsShareFunc int epicsShareAPI bucketRemoveItemPointerId (BUCKET *prb, void * const *pId);
/**
* \brief Remove an item identified by a string from the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Status value
*/
epicsShareFunc int epicsShareAPI bucketRemoveItemStringId (BUCKET *prb, const char *pId);
/**
* \brief Find an item identified by an unsigned int in the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Item's payload pointer, or NULL if not found
*/
epicsShareFunc void * epicsShareAPI bucketLookupItemUnsignedId (BUCKET *prb, const unsigned *pId);
/**
* \brief Find an item identified by a pointer in the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Item's payload pointer, or NULL if not found
*/
epicsShareFunc void * epicsShareAPI bucketLookupItemPointerId (BUCKET *prb, void * const *pId);
/**
* \brief Find an item identified by a string in the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Item's payload pointer, or NULL if not found
*/
epicsShareFunc void * epicsShareAPI bucketLookupItemStringId (BUCKET *prb, const char *pId);
/**
* \brief Find and delete an item identified by an unsigned int from the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Item's payload pointer, or NULL if not found
*/
epicsShareFunc void * epicsShareAPI bucketLookupAndRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId);
/**
* \brief Find and delete an item identified by a pointer from the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Item's payload pointer, or NULL if not found
*/
epicsShareFunc void * epicsShareAPI bucketLookupAndRemoveItemPointerId (BUCKET *prb, void * const *pId);
/**
* \brief Find and delete an item identified by a string from the table
* \param *prb Pointer to the hash table
* \param *pId Pointer to the identifier
* \return Item's payload pointer, or NULL if not found
*/
epicsShareFunc void * epicsShareAPI bucketLookupAndRemoveItemStringId (BUCKET *prb, const char *pId);
/*
* Status returned by bucketLib functions
/**
* \name Status values returned by some bucketLib functions
* @{
*/
/**
* \brief A synonym for S_bucket_success
*/
#define BUCKET_SUCCESS S_bucket_success
/**
* \brief Success, must be 0.
*/
#define S_bucket_success 0
/**
* \brief Memory allocation failed
*/
#define S_bucket_noMemory (M_bucket | 1) /*Memory allocation failed*/
/**
* \brief Identifier already in use
*/
#define S_bucket_idInUse (M_bucket | 2) /*Identifier already in use*/
/**
* \brief Unknown identifier
*/
#define S_bucket_uknId (M_bucket | 3) /*Unknown identifier*/
/** @} */
#ifdef __cplusplus
}
#endif
#endif /*INCbucketLibh*/

View File

@@ -4,11 +4,16 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* postfix.h
* Original Author: Bob Dalesio
* Date: 9-21-88
/**
* \file postfix.h
* \author Bob Dalesio, Andrew Johnson
*
* \brief The API for the EPICS Calculation Engine
*
* Defines macros and the routines provided by the calculation engine for
* subsystems that need to evaluate mathematical expressions.
*/
#ifndef INCpostfixh
@@ -16,69 +21,340 @@
#include "shareLib.h"
/** \brief Number of input arguments to a calc expression (A-L) */
#define CALCPERFORM_NARGS 12
/** \brief Size of the internal partial result stack */
#define CALCPERFORM_STACK 80
#define INFIX_TO_POSTFIX_SIZE(n) ((n)*21/6)
/* The above expression is an estimate of the maximum postfix buffer
* size needed for a given infix expression buffer (the argument must count
* the trailing nil byte in the input expression string). The actual size
/**
* \name Postfix and Infix Buffer Sizes
* @{
*/
/**
* \brief Calculate required size of postfix buffer from infix
*
* This macro calculates the maximum size of postfix buffer needed for an
* infix expression buffer of a given size. The argument \c n must count
* the trailing nil byte in the input expression string. The actual size
* needed is never larger than this value, although it is actually a
* few bytes smaller for some sizes.
*
* The maximum expansion from infix to postfix is for the sub-expression
* .1?.1:
\code
.1?.1:
\endcode
* which is 6 characters long and results in 21 bytes of postfix:
* .1 => LITERAL_DOUBLE + 8 byte value
* ? => COND_IF
* .1 => LITERAL_DOUBLE + 8 byte value
* : => COND_ELSE
* ...
* => COND_END
\code
.1 => LITERAL_DOUBLE + 8 byte value
? => COND_IF
.1 => LITERAL_DOUBLE + 8 byte value
: => COND_ELSE
...
=> COND_END
\endcode
* For other short expressions the factor 21/6 always gives a big enough
* postfix buffer (proven by hand, look at '1+' and '.1+' as well).
*/
#define INFIX_TO_POSTFIX_SIZE(n) ((n)*21/6)
/* These are not hard limits, just default sizes for the database */
/**
* \brief Size of a "standard" infix string.
*
* This is not a hard limit, just the default size for the database
*/
#define MAX_INFIX_SIZE 100
/**
* \brief Size of a "standard" postfix buffer.
*
* This is not a hard limit, just the default size for the database
*/
#define MAX_POSTFIX_SIZE INFIX_TO_POSTFIX_SIZE(MAX_INFIX_SIZE)
/** @} */
/* Error numbers from postfix */
/** \name Calc Engine Error Codes
* \note Changes in these errors must also be made in calcErrorStr().
* @{
*/
#define CALC_ERR_NONE 0 /* No error */
#define CALC_ERR_TOOMANY 1 /* Too many results returned */
#define CALC_ERR_BAD_LITERAL 2 /* Bad numeric literal */
#define CALC_ERR_BAD_ASSIGNMENT 3 /* Bad assignment target */
#define CALC_ERR_BAD_SEPERATOR 4 /* Comma without parentheses */
#define CALC_ERR_PAREN_NOT_OPEN 5 /* Close parenthesis without open */
#define CALC_ERR_PAREN_OPEN 6 /* Open parenthesis at end of expression */
#define CALC_ERR_CONDITIONAL 7 /* Unbalanced conditional ?: operators */
#define CALC_ERR_INCOMPLETE 8 /* Incomplete expression, operand missing */
#define CALC_ERR_UNDERFLOW 9 /* Runtime stack would underflow */
#define CALC_ERR_OVERFLOW 10 /* Runtime stack would overflow */
#define CALC_ERR_SYNTAX 11 /* Syntax error */
#define CALC_ERR_NULL_ARG 12 /* NULL or empty input argument */
#define CALC_ERR_INTERNAL 13 /* Internal error, bad element type */
/* Changes in the above errors must also be made in calcErrorStr() */
/** \brief No error */
#define CALC_ERR_NONE 0
/** \brief Too many results returned */
#define CALC_ERR_TOOMANY 1
/** \brief Bad numeric literal */
#define CALC_ERR_BAD_LITERAL 2
/** \brief Bad assignment target */
#define CALC_ERR_BAD_ASSIGNMENT 3
/** \brief Comma without parentheses */
#define CALC_ERR_BAD_SEPERATOR 4
/** \brief Close parenthesis without open */
#define CALC_ERR_PAREN_NOT_OPEN 5
/** \brief Open parenthesis at end of expression */
#define CALC_ERR_PAREN_OPEN 6
/** \brief Unbalanced conditional ?: operators */
#define CALC_ERR_CONDITIONAL 7
/** \brief Incomplete expression, operand missing */
#define CALC_ERR_INCOMPLETE 8
/** \brief Runtime stack would underflow */
#define CALC_ERR_UNDERFLOW 9
/** \brief Runtime stack would overflow */
#define CALC_ERR_OVERFLOW 10
/** \brief Syntax error */
#define CALC_ERR_SYNTAX 11
/** \brief NULL or empty input argument */
#define CALC_ERR_NULL_ARG 12
/** \brief Internal error, bad element type */
#define CALC_ERR_INTERNAL 13
/** @} */
#ifdef __cplusplus
extern "C" {
#endif
/** \brief Compile an infix expression into postfix byte-code
*
* Converts an expression from an infix string to postfix byte-code
*
* \param pinfix Pointer to the infix string
* \param ppostfix Pointer to the postfix buffer
* \param perror Place to return an error code
* \return Non-zero value in event of error
*
* It is the callers's responsibility to ensure that \c ppostfix points
* to sufficient storage to hold the postfix expression. The macro
* INFIX_TO_POSTFIX_SIZE(n) can be used to calculate an appropriate
* postfix buffer size from the length of the infix buffer.
*
* \note "n" must count the terminating nil byte too.
*
* -# The **infix expressions** that can be used are very similar
* to the C expression syntax, but with some additions and subtle
* differences in operator meaning and precedence. The string may
* contain a series of expressions separated by a semi-colon character ';'
* any one of which may actually provide the calculation result; however
* all of the other expressions included must assign their result to
* a variable. All alphabetic elements described below are case independent,
* so upper and lower case letters may be used and mixed in the variable
* and function names as desired. Spaces may be used anywhere within an
* expression except between the characters that make up a single expression element.
*
* -# ***Numeric Literals***
* The simplest expression element is a numeric literal, any (positive)
* number expressed using the standard floating point syntax that can be stored
* as a double precision value. This now includes the values Infinity and
* NaN (not a number). Note that negative numbers will be encoded as a
* positive literal to which the unary negate operator is applied.
*
* - Examples:
* - 1
* - 2.718281828459
* - Inf
*
* -# ***Constants***
* There are three trigonometric constants available to any expression
* which return a value:
* - pi returns the value of the mathematical constant pi.
* - D2R evaluates to pi/180 which, when used as a multiplier,
* converts an angle from degrees to radians.
* - R2D evaluates to 180/pi which as a multiplier converts an angle
* from radians to degrees.
*
* -# ***Variables***
* Variables are used to provide inputs to an expression, and are named
* using the single letters A through L inclusive or the keyword VAL which
* refers to the previous result of this calculation. The software that
* makes use of the expression evaluation code should document how the
* individual variables are given values; for the calc record type the input
* links INPA through INPL can be used to obtain these from other record fields,
* and VAL refers to the the VAL field (which can be overwritten from outside
* the record via Channel Access or a database link).
*
* -# ***Variable Assignment Operator***
* Recently added is the ability to assign the result of a sub-expression to
* any of the single letter variables, which can then be used in another
* sub-expression. The variable assignment operator is the character pair
* := and must immediately follow the name of the variable to receive the
* expression value. Since the infix string must return exactly one value, every
* expression string must have exactly one sub-expression that is not an
* assignment, which can appear anywhere in the string. Sub-expressions within
* the string are separated by a semi-colon character.
*
* - Examples:
* - B; B:=A
* - i:=i+1; a*sin(i*D2R)
*
* -# ***Arithmetic Operators***
* The usual binary arithmetic operators are provided: + - * and / with their
* usual relative precedence and left-to-right associativity, and - may also
* be used as a unary negate operator where it has a higher precedence and
* associates from right to left. There is no unary plus operator, so numeric
* literals cannot begin with a + sign.
*
* - Examples:
* - a*b + c
* - a/-4 - b
*
* Three other binary operators are also provided: % is the integer modulo operator,
* while the synonymous operators ** and ^ raise their left operand to the power of
* the right operand. % has the same precedence and associativity as * and /, while
* the power operators associate left-to-right and have a precedence in between * and
* unary minus.
*
* - Examples:
* - e:=a%10;
* - d:=a/10%10;
* - c:=a/100%10;
* - b:=a/1000%10;
* - b*4096+c*256+d*16+e
* - sqrt(a**2 + b**2)
*
* -# ***Algebraic Functions***
* Various algebraic functions are available which take parameters inside
* parentheses. The parameter seperator is a comma.
*
* - Absolute value: abs(a)
* - Exponential ea: exp(a)
* - Logarithm, base 10: log(a)
* - Natural logarithm (base e): ln(a) or loge(a)
* - n parameter maximum value: max(a, b, ...)
* - n parameter minimum value: min(a, b, ...)
* - Square root: sqr(a) or sqrt(a)
*
* -# ***Trigonometric Functions***
* Standard circular trigonometric functions, with angles expressed in radians:
* - Sine: sin(a)
* - Cosine: cos(a)
* - Tangent: tan(a)
* - Arcsine: asin(a)
* - Arccosine: acos(a)
* - Arctangent: atan(a)
* - 2 parameter arctangent: atan2(a, b)
* \note Note that these arguments are the reverse of the ANSI C function,
* so while C would return arctan(a/b) the calc expression engine returns arctan(b/a)
*
* -# ***Hyperbolic Trigonometry***
* The basic hyperbolic functions are provided, but no inverse functions
* (which are not provided by the ANSI C math library either).
* - Hyperbolic sine: sinh(a)
* - Hyperbolic cosine: cosh(a)
* - Hyperbolic tangent: tanh(a)
*
* -# ***Numeric Functions***
* The numeric functions perform operations related to the floating point
* numeric representation and truncation or rounding.
* - Round up to next integer: ceil(a)
* - Round down to next integer: floor(a)
* - Round to nearest integer: nint(a)
* - Test for infinite result: isinf(a)
* - Test for any non-numeric values: isnan(a, ...)
* - Test for all finite, numeric values: finite(a, ...)
* - Random number between 0 and 1: rndm
*
* -# ***Boolean Operators***
* These operators regard their arguments as true or false, where 0.0 is
* false and any other value is true.
*
* - Boolean and: a && b
* - Boolean or: a || b
* - Boolean not: !a
*
* -# ***Bitwise Operators***
* The bitwise operators convert their arguments to an integer (by truncation),
* perform the appropriate bitwise operation and convert back to a floating point
* value. Unlike in C though, ^ is not a bitwise exclusive-or operator.
*
* - Bitwise and: a & b or a and b
* - Bitwise or: a | b or a or b
* - Bitwise exclusive or: a xor b
* - Bitwise not (ones complement): ~a or not a
* - Bitwise left shift: a << b
* - Bitwise right shift: a >> b
*
* -# ***Relational Operators***
* Standard numeric comparisons between two values:
*
* - Less than: a < b
* - Less than or equal to: a <= b
* - Equal to: a = b or a == b
* - Greater than or equal to: a >= b
* - Greater than: a > b
* - Not equal to: a != b or a # b
*
* -# ***Conditional Operator***
* Expressions can use the C conditional operator, which has a lower
* precedence than all of the other operators except for the assignment operator.
*
* - condition ? true result : false result
* - Example:
* - a < 360 ? a+1 : 0
*
* -# ***Parentheses***
* Sub-expressions can be placed within parentheses to override operator precence rules.
* Parentheses can be nested to any depth, but the intermediate value stack used by
* the expression evaluation engine is limited to 80 results (which require an
* expression at least 321 characters long to reach).
*/
epicsShareFunc long
postfix(const char *pinfix, char *ppostfix, short *perror);
/** \brief Run the calculation engine
*
* Evaluates the postfix expression against a set ot input values.
*
* \param parg Pointer to an array of double values for the arguments A-L
* that can appear in the expression. Note that the argument values may be
* modified if the expression uses the assignment operator.
* \param presult Where to put the calculated result, which may be a NaN or Infinity.
* \param ppostfix The postfix expression created by postfix().
* \return Status value 0 for OK, or non-zero if an error is discovered
* during the evaluation process.
*/
epicsShareFunc long
calcPerform(double *parg, double *presult, const char *ppostfix);
/** \brief Find the inputs and outputs of an expression
*
* Software using the calc subsystem may need to know what expression
* arguments are used and/or modified by a particular expression. It can
* discover this from the postfix string by calling calcArgUsage(), which
* takes two pointers \c pinputs and \c pstores to a pair of unsigned long
* bitmaps which return that information to the caller. Passing a NULL value
* for either of these pointers is legal if only the other is needed.
*
* The least signficant bit (bit 0) of the bitmap at \c *pinputs will be set
* if the expression depends on the argument A, and so on through bit 11 for
* the argument L. An argument that is not used until after a value has been
* assigned to it will not be set in the pinputs bitmap, thus the bits can
* be used to determine whether a value needs to be supplied for their
* associated argument or not for the purposes of evaluating the expression.
*
* Bit 0 of the bitmap at \c *pstores will be set if the expression assigns
* a value to the argument A, bit 1 for argument B etc.
* \param ppostfix A postfix expression created by postfix().
* \param pinputs Bitmap pointer.
* \param pstores Bitmap pointer.
* \return The return value will be non-zero if the ppostfix expression was
* illegal, otherwise 0.
*/
epicsShareFunc long
calcArgUsage(const char *ppostfix, unsigned long *pinputs, unsigned long *pstores);
/** \brief Convert an error code to a string.
*
* Gives out a printable version of an individual error code.
* The error codes are macros defined here with names starting \c CALC_ERR_
* \param error Error code
* \return A string representation of the error code
*/
epicsShareFunc const char *
calcErrorStr(short error);
/** \brief Disassemble a postfix expression
*
* Convert the byte-code stream to text and print to stdout.
* \param pinst postfix instructions
*/
epicsShareFunc void
calcExprDump(const char *pinst);

View File

@@ -3,71 +3,105 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
// epicsAlgorithm.h
// Authors: Jeff Hill & Andrew Johnson
/**
* \file epicsAlgorithm.h
* \author Jeff Hill & Andrew Johnson
*
* \brief Contains a few templates out of the C++ standard header algorithm
*
* \note The templates are provided here in a much smaller file. Standard algorithm
* contains many templates for sorting and searching through C++ template containers
* which are not used in EPICS. If all you need from there is std::min(),
* std::max() and/or std::swap() your code may compile faster if you include
* epicsAlgorithm.h and use epicsMin(), epicsMax() and epicsSwap() instead.
*
* The C++ standard only requires types to be less-than comparable, so
* the epicsMin and epicsMax templates only use operator <.
*/
#ifndef __EPICS_ALGORITHM_H__
#define __EPICS_ALGORITHM_H__
#include "epicsMath.h"
// The C++ standard only requires types to be less-than comparable, so
// the epicsMin and epicsMax templates only use operator <
// epicsMin
/**
* Returns the smaller of a or b compared using a<b.
*
*/
template <class T>
inline const T& epicsMin (const T& a, const T& b)
{
return (b < a) ? b : a;
}
// If b is a NaN the above template returns a, but should return NaN.
// These specializations ensure that epicsMin(x,NaN) == NaN
/**
* Returns the smaller of a or b compared using a<b.
*
* \note If b is a NaN the above template returns a, but should return NaN.
* These specializations ensure that epicsMin(x,NaN) == NaN
*/
template <>
inline const float& epicsMin (const float& a, const float& b)
{
return (b < a) || isnan(b) ? b : a;
}
/**
* Returns the smaller of a or b compared using a<b.
*
* \note If b is a NaN the above template returns a, but should return NaN.
* These specializations ensure that epicsMin(x,NaN) == NaN
*/
template <>
inline const double& epicsMin (const double& a, const double& b)
{
return (b < a) || isnan(b) ? b : a;
}
// epicsMax
/**
* Returns the larger of a or b compared using a<b.
*
*/
template <class T>
inline const T& epicsMax (const T& a, const T& b)
{
return (a < b) ? b : a;
}
// If b is a NaN the above template returns a, but should return NaN.
// These specializations ensure that epicsMax(x,NaN) == NaN
/**
* Returns the larger of a or b compared using a<b.
*
* \note If b is a NaN the above template returns a, but should return NaN.
* These specializations ensure that epicsMax(x,NaN) == NaN
*/
template <>
inline const float& epicsMax (const float& a, const float& b)
{
return (a < b) || isnan(b) ? b : a;
}
/**
* Returns the larger of a or b compared using a<b.
*
* \note If b is a NaN the above template returns a, but should return NaN.
* These specializations ensure that epicsMax(x,NaN) == NaN
*/
template <>
inline const double& epicsMax (const double& a, const double& b)
{
return (a < b) || isnan(b) ? b : a;
}
// epicsSwap
/**
* Swaps the values of a and b.
*
* \note The data type must support both copy-construction and assignment.
*
*/
template <class T>
inline void epicsSwap(T& a, T& b)
{

View File

@@ -3,15 +3,33 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Jim Kowalkowski and Marty Kraimer
* Date: 4/97
/**
* \file dbmf.h
* \author Jim Kowalkowski, Marty Kraimer
*
* A library to manage storage that is allocated and then freed.
* \brief A library to manage storage that is allocated and quickly freed.
*
* Database Macro/Free describes a facility that prevents memory fragmentation
* when temporary storage is being allocated and freed a short time later, at
* the same time that much longer-lived storage is also being allocated, such
* as when parsing items for the IOC database while also creating records.
*
* Routines whin iocCore like dbLoadDatabase() have the following attributes:
* - They repeatedly call malloc() followed soon afterwards by a call to
* free() the temporaryily allocated storage.
* - Between those calls to malloc() and free(), additional calls to
* malloc() are made that do NOT have an associated free().
*
* \note In some environment, e.g. vxWorks, this behavior causes severe memory
* fragmentation.
*
* \note This facility should NOT be used by code that allocates storage and
* then keeps it for a considerable period of time before releasing. Such code
* should consider using the freeList library.
*/
#ifndef DBMF_H
#define DBMF_H
@@ -23,25 +41,71 @@
extern "C" {
#endif
/**
* \brief Initialize the facility
* \param size The maximum size request from dbmfMalloc() that will be
* allocated from the dbmf pool (Size is always made a multiple of 8).
* \param chunkItems Each time malloc() must be called size*chunkItems bytes
* are allocated.
* \return 0 on success, -1 if already initialized
*
* \note If dbmfInit() is not called before one of the other routines then it
* is automatically called with size=64 and chunkItems=10
*/
epicsShareFunc int dbmfInit(size_t size, int chunkItems);
/**
* \brief Allocate memory.
* \param bytes If bytes > size then malloc() is used to allocate the memory.
* \return Pointer to the newly-allocated memory, or NULL on failure.
*/
epicsShareFunc void * dbmfMalloc(size_t bytes);
/**
* \brief Duplicate a string.
*
* Create a copy of the input string.
* \param str Pointer to the null-terminated string to be copied.
* \return A pointer to the new copy, or NULL on failure.
*/
epicsShareFunc char * dbmfStrdup(const char *str);
/**
* \brief Duplicate a string (up to len bytes).
*
* Copy at most len bytes of the input string into a new buffer. If no nil
* terminator is seen in the first \c len bytes a nil terminator is added.
* \param str Pointer to the null-terminated string to be copied.
* \param len Max number of bytes to copy.
* \return A pointer to the new string, or NULL on failure.
*/
epicsShareFunc char * dbmfStrndup(const char *str, size_t len);
/**
* \brief Concatenate three strings.
* Returns a pointer to a null-terminated string made by concatenating the
* three input strings.
* \param lhs Start string to which the others get concatenated to (left part).
* \param mid Next string to be concatenated to the lhs (mid part).
* \param rhs Last string to be concatenated to the lhs+mid (right part).
* \return A pointer to the new string, or NULL on failure.
*/
epicsShareFunc char * dbmfStrcat3(const char *lhs, const char *mid,
const char *rhs);
/**
* \brief Free the memory allocated by dbmfMalloc.
* \param bytes Pointer to memory obtained from dbmfMalloc(), dbmfStrdup(),
* dbmfStrndup() or dbmfStrcat3().
*/
epicsShareFunc void dbmfFree(void *bytes);
/**
* \brief Free all chunks that contain only free items.
*/
epicsShareFunc void dbmfFreeChunks(void);
/**
* \brief Show the status of the dbmf memory pool.
* \param level Detail level.
* \return 0.
*/
epicsShareFunc int dbmfShow(int level);
/* Rules:
* 1) Size is always made a multiple of 8.
* 2) if dbmfInit is not called before one of the other routines then it
* is automatically called with size=64 and chunkItems=10
* 3) These routines should only be used to allocate storage that will
* shortly thereafter be freed.
* 4) dbmfFreeChunks can only free chunks that contain only free items
*/
#ifdef __cplusplus
}
#endif

View File

@@ -6,10 +6,23 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: John Winans (ANL)
* Andrew Johnson <anj@aps.anl.gov>
/**
* \file ellLib.h
* \author John Winans (ANL)
* \author Andrew Johnson (ANL)
*
* \brief A doubly-linked list library
*
* This provides similar functionality to the VxWorks lstLib library.
*
* Supports the creation and maintenance of a doubly-linked list. The user
* supplies a list descriptor (type \c ELLLIST) that will contain pointers to
* the first and last nodes in the list, and a count of the number of
* nodes in the list. The nodes in the list can be any user-defined structure,
* but they must reserve space for two pointers as their first elements.
* Both the forward and backward chains are terminated with a NULL pointer.
*/
#ifndef INC_ellLib_H
#define INC_ellLib_H
@@ -19,46 +32,182 @@
extern "C" {
#endif
/** \brief List node type.
*
* A list node (an \c ELLNODE) must be embedded in the structure to be placed
* on the list, ideally as the first member of that structure.
*
* If the node is elsewhere in the structure, care must be taken to convert
* between the structure pointer and the node pointer and back every time when
* calling routines in the ellLib API. The ellFree() and ellFree2() routines
* cannot be used with such a list.
*/
typedef struct ELLNODE {
struct ELLNODE *next;
struct ELLNODE *previous;
struct ELLNODE *next; /**< \brief Pointer to next node in list */
struct ELLNODE *previous; /**< \brief Pointer to previous node in list */
} ELLNODE;
/** \brief Value of a terminal node
*/
#define ELLNODE_INIT {NULL, NULL}
/** \brief List header type
*/
typedef struct ELLLIST {
ELLNODE node;
int count;
ELLNODE node; /**< \brief Pointers to the first and last nodes on list */
int count; /**< \brief Number of nodes on the list */
} ELLLIST;
/** \brief Value of an empty list
*/
#define ELLLIST_INIT {ELLNODE_INIT, 0}
/** \brief Pointer to free() for use by ellFree() macro.
*
* This is required for use on Windows, where each DLL has its own free()
* function. The ellFree() macro passes the application's version of free()
* to the ellFree2() function.
*/
typedef void (*FREEFUNC)(void *);
/** \brief Initialize a list type
* \param PLIST Pointer to list header to be initialized
*/
#define ellInit(PLIST) {\
(PLIST)->node.next = (PLIST)->node.previous = NULL;\
(PLIST)->count = 0;\
}
/** \brief Report the number of nodes in a list
* \param PLIST Pointer to list descriptor
* \return Number of nodes in the list
*/
#define ellCount(PLIST) ((PLIST)->count)
/** \brief Find the first node in list
* \param PLIST Pointer to list descriptor
* \return Pointer to first node in the list
*/
#define ellFirst(PLIST) ((PLIST)->node.next)
/** \brief Find the last node in list
* \param PLIST Pointer to list descriptor
* \return Pointer to last node in the list
*/
#define ellLast(PLIST) ((PLIST)->node.previous)
/** \brief Find the next node in list
* \param PNODE Pointer to node whose successor is to be found
* \return Pointer to the node following \c PNODE
*/
#define ellNext(PNODE) ((PNODE)->next)
/** \brief Find the previous node in list
* \param PNODE Pointer to node whose predecessor is to be found
* \return Pointer to the node prior to \c PNODE
*/
#define ellPrevious(PNODE) ((PNODE)->previous)
/** \brief Free up the list
* \param PLIST List for which to free all nodes
*/
#define ellFree(PLIST) ellFree2(PLIST, free)
/**
* \brief Adds a node to the end of a list
* \param pList Pointer to list descriptor
* \param pNode Pointer to node to be added
*/
epicsShareFunc void ellAdd (ELLLIST *pList, ELLNODE *pNode);
/**
* \brief Concatenates a list to the end of another list.
* The list to be added is left empty. Either list (or both)
* can be empty at the beginning of the operation.
* \param pDstList Destination list
* \param pAddList List to be added to \c pDstList
*/
epicsShareFunc void ellConcat (ELLLIST *pDstList, ELLLIST *pAddList);
/**
* \brief Deletes a node from a list.
* \param pList Pointer to list descriptor
* \param pNode Pointer to node to be deleted
*/
epicsShareFunc void ellDelete (ELLLIST *pList, ELLNODE *pNode);
/**
* \brief Extract a sublist from a list.
* \param pSrcList Pointer to source list
* \param pStartNode First node in \c pSrcList to be extracted
* \param pEndNode Last node in \c pSrcList to be extracted
* \param pDstList Pointer to list where to put extracted list
*/
epicsShareFunc void ellExtract (ELLLIST *pSrcList, ELLNODE *pStartNode, ELLNODE *pEndNode, ELLLIST *pDstList);
/**
* \brief Deletes and returns the first node from a list
* \param pList Pointer to list from which to get node
* \return Pointer to the first node from the list, or NULL if the list is empty
*/
epicsShareFunc ELLNODE * ellGet (ELLLIST *pList);
/**
* \brief Deletes and returns the last node from a list.
* \param pList Pointer to list from which to get node
* \return Pointer to the last node from the list, or NULL if the list is empty
*/
epicsShareFunc ELLNODE * ellPop (ELLLIST *pList);
/**
* \brief Inserts a node into a list immediately after a specific node
* \param plist Pointer to list into which to insert node
* \param pPrev Pointer to the node after which to insert
* \param pNode Pointer to the node to be inserted
* \note If \c pPrev is NULL \c pNode will be inserted at the head of the list
*/
epicsShareFunc void ellInsert (ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode);
/**
* \brief Find the Nth node in a list
* \param pList Pointer to list from which to find node
* \param nodeNum Index of the node to be found
* \return Pointer to the element at index \c nodeNum in pList, or NULL if
* there is no such node in the list.
* \note The first node has index 1.
*/
epicsShareFunc ELLNODE * ellNth (ELLLIST *pList, int nodeNum);
/**
* \brief Find the list node \c nStep steps away from a specified node
* \param pNode The known node
* \param nStep How many steps to take, may be negative to step backwards
* \return Pointer to the node \c nStep nodes from \c pNode, or NULL if there
* is no such node in the list.
*/
epicsShareFunc ELLNODE * ellNStep (ELLNODE *pNode, int nStep);
/**
* \brief Find the index of a specific node in a list
* \param pList Pointer to list to search
* \param pNode Pointer to node to search for
* \return The node's index, or -1 if it cannot be found on the list.
* \note The first node has index 1.
*/
epicsShareFunc int ellFind (ELLLIST *pList, ELLNODE *pNode);
typedef int (*pListCmp)(const ELLNODE* A, const ELLNODE* B);
epicsShareFunc void ellSortStable(ELLLIST *pList, pListCmp);
/**
* \brief Stable (MergeSort) of a given list.
* \param pList Pointer to list to be sorted
* \param pListCmp Compare function to be used
* \note The comparison function cmp(A,B) is expected
* to return -1 for A<B, 0 for A==B, and 1 for A>B.
*
* \note Use of mergesort algorithm based on analysis by
* http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
*/
epicsShareFunc void ellSortStable(ELLLIST *pList, pListCmp pListCmp);
/**
* \brief Free all the nodes in a list.
*
* This routine empties a list, calling freeFunc() for every node on it.
* \param pList List from which to free all nodes
* \param freeFunc The free() routine to be called
* \note The nodes in the list are free()'d on the assumption that the node
* structures were malloc()'d one-at-a-time and that the ELLNODE structure is
* the first member of the parent structure.
*/
epicsShareFunc void ellFree2 (ELLLIST *pList, FREEFUNC freeFunc);
/**
* \brief Verifies that the list is consistent
* \param pList List to be verified
*/
epicsShareFunc void ellVerify (ELLLIST *pList);
#ifdef __cplusplus

View File

@@ -4,26 +4,27 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Roger A. Cole
* Date: 07-20-91
/**
* \file envDefs.h
* \author Roger A. Cole
*
* \brief Routines to get and set EPICS environment parameters.
*
* This file defines environment parameters used by EPICS and the
* routines used to get and set those parameter values.
*
* The ENV_PARAM's declared here are defined in the generated file
* envData.c by the bldEnvData.pl Perl script, which parses this file
* and the build system's CONFIG_ENV and CONFIG_SITE_ENV files.
* User programs can define their own environment parameters for their
* own use--the only caveat is that such parameters aren't automatically
* setup by EPICS.
*
* \note bldEnvData.pl looks for "epicsShareExtern const ENV_PARAM <name>;"
*/
/****************************************************************************
* TITLE envDefs.h - definitions for environment get/set routines
*
* DESCRIPTION
* This file defines the environment parameters for EPICS. These
* ENV_PARAM's are created in envData.c by bldEnvData for
* use by EPICS programs running under UNIX and VxWorks.
*
* User programs can define their own environment parameters for their
* own use--the only caveat is that such parameters aren't automatically
* setup by EPICS.
*
*****************************************************************************/
#ifndef envDefsH
#define envDefsH
@@ -34,14 +35,14 @@ extern "C" {
#include "shareLib.h"
/**
* \brief A structure to hold a single environment parameter
*/
typedef struct envParam {
char *name; /* text name of the parameter */
char *pdflt;
char *name; /**< \brief Name of the parameter */
char *pdflt; /**< \brief Default value */
} ENV_PARAM;
/*
* bldEnvData.pl looks for "epicsShareExtern const ENV_PARAM <name>;"
*/
epicsShareExtern const ENV_PARAM EPICS_CA_ADDR_LIST;
epicsShareExtern const ENV_PARAM EPICS_CA_CONN_TMO;
epicsShareExtern const ENV_PARAM EPICS_CA_AUTO_ADDR_LIST;
@@ -57,7 +58,7 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_IGNORE_ADDR_LIST;
epicsShareExtern const ENV_PARAM EPICS_CAS_AUTO_BEACON_ADDR_LIST;
epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_ADDR_LIST;
epicsShareExtern const ENV_PARAM EPICS_CAS_SERVER_PORT;
epicsShareExtern const ENV_PARAM EPICS_CA_BEACON_PERIOD; /* deprecated */
epicsShareExtern const ENV_PARAM EPICS_CA_BEACON_PERIOD; /**< \brief deprecated */
epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PERIOD;
epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT;
epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS;
@@ -74,30 +75,167 @@ epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_FILE_COMMAND;
epicsShareExtern const ENV_PARAM IOCSH_PS1;
epicsShareExtern const ENV_PARAM IOCSH_HISTSIZE;
epicsShareExtern const ENV_PARAM IOCSH_HISTEDIT_DISABLE;
epicsShareExtern const ENV_PARAM *env_param_list[];
struct in_addr;
epicsShareFunc char * epicsShareAPI
/**
* \brief Get value of a configuration parameter
*
* Gets the value of a configuration parameter from the environment
* and copies it into the caller's buffer. If the parameter isn't
* set in the environment, the default value for the parameter is
* copied instead. If neither provides a non-empty string the buffer
* is set to '\0' and NULL is returned.
*
* \param pParam Pointer to config param structure.
* \param bufDim Dimension of parameter buffer
* \param pBuf Pointer to parameter buffer
* \return Pointer to the environment variable value string, or
* NULL if no parameter value and default value was empty.
*/
epicsShareFunc char * epicsShareAPI
envGetConfigParam(const ENV_PARAM *pParam, int bufDim, char *pBuf);
epicsShareFunc const char * epicsShareAPI
/**
* \brief Get a configuration parameter's value or default string.
*
* \param pParam Pointer to config param structure.
* \return Pointer to the environment variable value string, or to
* the default value for the parameter, or NULL if those strings
* were empty or not set.
*/
epicsShareFunc const char * epicsShareAPI
envGetConfigParamPtr(const ENV_PARAM *pParam);
epicsShareFunc long epicsShareAPI
/**
* \brief Print the value of a configuration parameter.
*
* \param pParam Pointer to config param structure.
* \return 0
*/
epicsShareFunc long epicsShareAPI
envPrtConfigParam(const ENV_PARAM *pParam);
epicsShareFunc long epicsShareAPI
/**
* \brief Get value of an inet addr config parameter.
*
* Gets the value of a configuration parameter and copies it into
* the caller's (struct in_addr) buffer. If the configuration parameter
* isn't found in the environment, the default value for that parameter
* will be used. The resulting string is converted from a dotted-quad
* format or looked up using the DNS and copied into the inet structure.
*
* If no parameter is found and there is no default, then -1 is
* returned and the callers buffer is unmodified.
*
* \param pParam Pointer to config param structure.
* \param pAddr Pointer to struct to receive inet addr.
* \return 0, or -1 if an error is encountered
*/
epicsShareFunc long epicsShareAPI
envGetInetAddrConfigParam(const ENV_PARAM *pParam, struct in_addr *pAddr);
epicsShareFunc long epicsShareAPI
/**
* \brief Get value of a double configuration parameter.
*
* Gets the value of a configuration parameter, converts it into a
* \c double value and copies that into the caller's buffer. If the
* configuration parameter isn't found in the environment, the
* default value for the parameter is used instead.
*
* If no parameter is found and there is no default, then -1 is
* returned and the callers buffer is unmodified.
*
* \param pParam Pointer to config param structure.
* \param pDouble Pointer to place to store value.
* \return 0, or -1 if an error is encountered
*/
epicsShareFunc long epicsShareAPI
envGetDoubleConfigParam(const ENV_PARAM *pParam, double *pDouble);
epicsShareFunc long epicsShareAPI
/**
* \brief Get value of a long configuration parameter.
*
* Gets the value of a configuration parameter, converts it into a
* \c long value and copies that into the caller's buffer. If the
* configuration parameter isn't found in the environment, the
* default value for the parameter is used instead.
*
* If no parameter is found and there is no default, then -1 is
* returned and the callers buffer is unmodified.
*
* \param pParam Pointer to config param structure.
* \param pLong Pointer to place to store value.
* \return 0, or -1 if an error is encountered
*/
epicsShareFunc long epicsShareAPI
envGetLongConfigParam(const ENV_PARAM *pParam, long *pLong);
epicsShareFunc unsigned short epicsShareAPI envGetInetPortConfigParam
/**
* \brief Get value of a port number configuration parameter.
*
* Returns the value of a configuration parameter that represents
* an inet port number. If no environment variable is found the
* default parameter value is used, and if that is also unset the
* \c defaultPort argument returned instead. The integer value must
* fall between the values IPPORT_USERRESERVED and USHRT_MAX or the
* \c defaultPort argument will be substituted instead.
*
* \param pEnv Pointer to config param structure.
* \param defaultPort Port number to be used if environment settings invalid.
* \return Port number.
*/
epicsShareFunc unsigned short epicsShareAPI envGetInetPortConfigParam
(const ENV_PARAM *pEnv, unsigned short defaultPort);
/**
* \brief Get value of a boolean configuration parameter.
*
* Gets the value of a configuration parameter, and puts the value
* 0 or 1 into the caller's buffer depending on the value. If the
* configuration parameter isn't found in the environment, the
* default value for the parameter is used instead.
*
* A value is treated as True (1) if it compares equal to the
* string "yes" with a case-independent string comparison. All
* other strings are treated as False (0).
*
* If no parameter is found and there is no default, then -1 is
* returned and the callers buffer is unmodified.
*
* \param pParam Pointer to config param structure.
* \param pBool Pointer to place to store value.
* \return 0, or -1 if an error is encountered
*/
epicsShareFunc long epicsShareAPI
envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool);
/**
* \brief Prints all configuration parameters and their current value.
*
* \return 0
*/
epicsShareFunc long epicsShareAPI epicsPrtEnvParams(void);
/**
* \brief Set an environment variable's value
*
* The setenv() routine is not available on all operating systems.
* This routine provides a portable alternative for all EPICS targets.
* \param name Environment variable name.
* \param value New value for environment variable.
*/
epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value);
/**
* \brief Clear the value of an environment variable
* \param name Environment variable name.
*/
epicsShareFunc void epicsShareAPI epicsEnvUnset (const char *name);
/**
* \brief Print value of an environment variable, or all variables
*
* \param name Environment variable name, or NULL to show all.
*/
epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name);
#ifdef __cplusplus
@@ -105,4 +243,3 @@ epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name);
#endif
#endif /*envDefsH*/

View File

@@ -85,27 +85,27 @@ epicsShareFunc const iocshVarDef * epicsShareAPI iocshFindVariable(
/* This should only be called when iocsh is no longer needed*/
epicsShareFunc void epicsShareAPI iocshFree(void);
/** shorthand for @code iocshLoad(pathname, NULL) @endcode */
/** shorthand for \code iocshLoad(pathname, NULL) \endcode */
epicsShareFunc int epicsShareAPI iocsh(const char *pathname);
/** shorthand for @code iocshRun(cmd, NULL) @endcode */
/** shorthand for \code iocshRun(cmd, NULL) \endcode */
epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd);
/** Read and evaluate IOC shell commands from the given file.
* @param pathname Path to script file
* @param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y"
* @return 0 on success, non-zero on error
* \param pathname Path to script file
* \param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y"
* \return 0 on success, non-zero on error
*/
epicsShareFunc int epicsShareAPI iocshLoad(const char *pathname, const char* macros);
/** Evaluate a single IOC shell command
* @param cmd Command string. eg. "echo \"something or other\""
* @param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y"
* @return 0 on success, non-zero on error
* \param cmd Command string. eg. "echo \"something or other\""
* \param macros NULL or a comma seperated list of macro definitions. eg. "VAR1=x,VAR2=y"
* \return 0 on success, non-zero on error
*/
epicsShareFunc int epicsShareAPI iocshRun(const char *cmd, const char* macros);
/** @brief Signal error from an IOC shell function.
/** \brief Signal error from an IOC shell function.
*
* @param err 0 - success (no op), !=0 - error
* @return The err argument value.
* \param err 0 - success (no op), !=0 - error
* \return The err argument value.
*/
epicsShareFunc int iocshSetError(int err);

View File

@@ -4,20 +4,26 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Definitions for macro substitution library (macLib)
/**
* \file macLib.h
* \brief Text macro substitution routines
* \author William Lupton, W. M. Keck Observatory
*
* William Lupton, W. M. Keck Observatory
* This general purpose macro substitution library
* is used for all macro substitutions in EPICS Base.
*
* Most routines return 0 (OK) on success, -1 (ERROR) on failure,
* or small positive values for extra info.
* The macGetValue() and macExpandString() routines depart from this
* and return information both on success / failure and on value length.
* Errors and warnings are reported using errlogPrintf().
*/
#ifndef INCmacLibH
#define INCmacLibH
/*
* EPICS include files needed by this file
*/
#include "ellLib.h"
#include "shareLib.h"
@@ -25,137 +31,275 @@
extern "C" {
#endif
/*
* Maximum size of macro name or value string (simpler to make fixed)
/** \brief Maximum size of a macro name or value
*/
#define MAC_SIZE 256
/*
* Macro substitution context. One of these contexts is allocated each time
* macCreateHandle() is called
/** \brief Macro substitution context, for use by macLib routines only.
*
* An application may have multiple active contexts if desired.
*/
typedef struct {
long magic; /* magic number (used for authentication) */
int dirty; /* values need expanding from raw values? */
int level; /* scoping level */
int debug; /* debugging level */
ELLLIST list; /* macro name / value list */
int flags; /* operating mode flags */
long magic; /**< \brief magic number (used for authentication) */
int dirty; /**< \brief values need expanding from raw values? */
int level; /**< \brief scoping level */
int debug; /**< \brief debugging level */
ELLLIST list; /**< \brief macro name / value list */
int flags; /**< \brief operating mode flags */
} MAC_HANDLE;
/*
* Function prototypes (core library)
/** \name Core Library
* The core library provides a minimal set of basic operations.
* @{
*/
epicsShareFunc long /* 0 = OK; <0 = ERROR */
/**
* \brief Creates a new macro substitution context.
* \return 0 = OK; <0 = ERROR
*/
epicsShareFunc long
epicsShareAPI macCreateHandle(
MAC_HANDLE **handle, /* address of variable to receive pointer */
/* to new macro substitution context */
MAC_HANDLE **handle, /**< pointer to variable to receive pointer
to new macro substitution context */
const char * pairs[] /* pointer to NULL-terminated array of */
/* {name,value} pair strings; a NULL */
/* value implies undefined; a NULL */
/* argument implies no macros */
const char * pairs[] /**< pointer to NULL-terminated array of
{name,value} pair strings. A NULL
value implies undefined; a NULL \c pairs
argument implies no macros. */
);
/**
* \brief Disable or enable warning messages.
*
* The macExpandString() routine prints warnings when it cant expand a macro.
* This routine can be used to silence those warnings. A non zero value will
* suppress the warning messages from subsequent library routines given the
* same \c handle.
*/
epicsShareFunc void
epicsShareAPI macSuppressWarning(
MAC_HANDLE *handle, /* opaque handle */
MAC_HANDLE *handle, /**< opaque handle */
int falseTrue /*0 means issue, 1 means suppress*/
int falseTrue /**< 0 means issue, 1 means suppress*/
);
epicsShareFunc long /* strlen(dest), <0 if any macros are */
/* undefined */
epicsShareAPI macExpandString(
MAC_HANDLE *handle, /* opaque handle */
const char *src, /* source string */
char *dest, /* destination string */
long capacity /* capacity of destination buffer (dest) */
);
epicsShareFunc long /* strlen(value) */
epicsShareAPI macPutValue(
MAC_HANDLE *handle, /* opaque handle */
const char *name, /* macro name */
const char *value /* macro value */
);
epicsShareFunc long /* strlen(value), <0 if undefined */
epicsShareAPI macGetValue(
MAC_HANDLE *handle, /* opaque handle */
const char *name, /* macro name or reference */
char *value, /* string to receive macro value or name */
/* argument if macro is undefined */
long capacity /* capacity of destination buffer (value) */
);
epicsShareFunc long /* 0 = OK; <0 = ERROR */
epicsShareAPI macDeleteHandle(
MAC_HANDLE *handle /* opaque handle */
);
epicsShareFunc long /* 0 = OK; <0 = ERROR */
epicsShareAPI macPushScope(
MAC_HANDLE *handle /* opaque handle */
);
epicsShareFunc long /* 0 = OK; <0 = ERROR */
epicsShareAPI macPopScope(
MAC_HANDLE *handle /* opaque handle */
);
epicsShareFunc long /* 0 = OK; <0 = ERROR */
epicsShareAPI macReportMacros(
MAC_HANDLE *handle /* opaque handle */
);
/*
* Function prototypes (utility library)
/**
* \brief Expand a string which may contain macro references.
* \return Returns the length of the expanded string, <0 if any macro are
* undefined
*
* This routine parses the \c src string looking for macro references and
* passes any it finds to macGetValue() for translation.
*
* \note The return value is similar to that of macGetValue(). Its absolute
* value is the number of characters copied to \c dest. If the return value
* is negative, at least one undefined macro was left unexpanded.
*/
epicsShareFunc long /* #defns encountered; <0 = ERROR */
epicsShareFunc long
epicsShareAPI macExpandString(
MAC_HANDLE *handle, /**< opaque handle */
const char *src, /**< source string */
char *dest, /**< destination string */
long capacity /**< capacity of destination buffer (dest) */
);
/**
* \brief Sets the value of a specific macro.
* \return Returns the length of the value string.
* \note If \c value is NULL, all instances of \c name are undefined at
* all scoping levels (the named macro doesn't have to exist in this case).
* Macros referenced in \c value need not be defined at this point.
*/
epicsShareFunc long
epicsShareAPI macPutValue(
MAC_HANDLE *handle, /**< opaque handle */
const char *name, /**< macro name */
const char *value /**< macro value */
);
/**
* \brief Returns the value of a macro
* \return Returns the length of the value string, <0 if undefined
*
* \c value will be zero-terminated if the length of the value is less than
* \c capacity. The return value is the number of characters copied to
* \c value (see below for behavior if the macro is undefined). If \c capacity
* is zero, no characters will be copied to \c value (which may be NULL)
* and the call can be used to check whether the macro is defined.
*
* \note Truncation of the value is not reported, applications should assume
* that truncation has occurred if the return value is equal to capacity.
*
* If the macro is undefined, the macro reference will be returned in
* the value string (if permitted by maxlen) and the function value will
* be _minus_ the number of characters copied. Note that treatment of
* \c capacity is intended to be consistent with the strncpy() routine.
*
* If the value contains macro references, these references will be
* expanded recursively. This expansion will detect a direct or indirect
* self reference.
*
* Macro references begin with a "$" immediately followed by either a
* "(" or a "{" character. The macro name comes next, and may optionally
* be succeeded by an "=" and a default value, which will be returned if
* the named macro is undefined at the moment of expansion. A reference
* is terminated by the matching ")" or "}" character.
*/
epicsShareFunc long
epicsShareAPI macGetValue(
MAC_HANDLE *handle, /**< opaque handle */
const char *name, /**< macro name or reference */
char *value, /**< string to receive macro value or name
argument if macro is undefined */
long capacity /**< capacity of destination buffer (value) */
);
/**
* \brief Marks a handle invalid, and frees all storage associated with it
* \return 0 = OK; <0 = ERROR
* \note Note that this does not free any strings into which macro values have
* been returned. Macro values are always returned into strings which
* were pre-allocated by the caller.
*/
epicsShareFunc long
epicsShareAPI macDeleteHandle(
MAC_HANDLE *handle /**< opaque handle */
);
/**
* \brief Marks the start of a new scoping level
* \return 0 = OK; <0 = ERROR
*
* Marks all macro definitions added after this call as belonging
* to another scope. These macros will be lost on a macPopScope()
* call and those at the current scope will be re-instated.
*/
epicsShareFunc long
epicsShareAPI macPushScope(
MAC_HANDLE *handle /**< opaque handle */
);
/**
* \brief Retrieve the last pushed scope (like stack operations)
* \return 0 = OK; <0 = ERROR
*
* See macPushScope()
*/
epicsShareFunc long
epicsShareAPI macPopScope(
MAC_HANDLE *handle /**< opaque handle */
);
/**
* \brief Reports details of current definitions
* \return 0 = OK; <0 = ERROR
* This sends details of current definitions to standard output,
* and is intended purely for debugging purposes.
*/
epicsShareFunc long
epicsShareAPI macReportMacros(
MAC_HANDLE *handle /**< opaque handle */
);
/** @} */
/** \name Utility Library
* These convenience functions are intended for applications to use and
* provide a more convenient interface for some purposes.
* @{
*/
/**
* \brief Parse macro definitions into an array of {name, value} pairs.
* \return Number of macros found; <0 = ERROR
*
* This takes a set of macro definitions in "a=xxx,b=yyy" format and
* converts them into an array of pointers to character strings which
* are, in order, "first name", "first value", "second name", "second
* value" etc. The array is terminated with two NULL pointers and all
* storage is allocated contiguously so that it can be freed with a
* single call to free().
*
* This routine is independent of any handle and provides a generally
* useful service which may be used elsewhere. Any macro references in
* values are not expanded at this point since the referenced macros may
* be defined or redefined before the macro actually has to be
* translated.
*
* Shell-style escapes and quotes are supported, as are things like
* "A=B,B=$(C$(A)),CA=CA,CB=CB" (sets B to "CB"). White space is
* significant within values but ignored elsewhere (i.e. surrounding "="
* and "," characters).
*
* The function returns the number of definitions encountered, or -1 if
* the supplied string is invalid.
*/
epicsShareFunc long
epicsShareAPI macParseDefns(
MAC_HANDLE *handle, /* opaque handle; can be NULL if default */
/* special characters are to be used */
MAC_HANDLE *handle, /**< opaque handle; may be NULL if debug
messages are not required. */
const char *defns, /* macro definitions in "a=xxx,b=yyy" */
/* format */
const char *defns, /**< macro definitions in "a=xxx,b=yyy"
format */
char **pairs[] /* address of variable to receive pointer */
/* to NULL-terminated array of {name, */
/* value} pair strings; all storage is */
/* allocated contiguously */
char **pairs[] /**< address of variable to receive pointer
to NULL-terminated array of {name,
value} pair strings; all storage is
allocated contiguously */
);
epicsShareFunc long /* #macros defined; <0 = ERROR */
/**
* \brief Install set of {name, value} pairs as definitions
* \return Number of macros defined; <0 = ERROR
*
* This takes an array of pairs as defined above and installs them as
* definitions by calling macPutValue(). The pairs array is terminated
* by a NULL pointer.
*/
epicsShareFunc long
epicsShareAPI macInstallMacros(
MAC_HANDLE *handle, /* opaque handle */
MAC_HANDLE *handle, /**< opaque handle */
char *pairs[] /* pointer to NULL-terminated array of */
/* {name,value} pair strings; a NULL */
/* value implies undefined; a NULL */
/* argument implies no macros */
char *pairs[] /**< pointer to NULL-terminated array of
{name,value} pair strings; a NULL
value implies undefined; a NULL
argument implies no macros */
);
epicsShareFunc char * /* expanded string; NULL if any undefined macros */
/**
* \brief Expand environment variables in a string.
* \return Expanded string; NULL if any undefined macros were used.
*
* This routine expands a string which may contain macros that are
* environment variables. It parses the string looking for such
* references and passes them to macGetValue() for translation. It uses
* malloc() to allocate space for the expanded string and returns a
* pointer to this null-terminated string. It returns NULL if the source
* string contains any undefined references.
*/
epicsShareFunc char *
epicsShareAPI macEnvExpand(
const char *str /* string to be expanded */
const char *str /**< string to be expanded */
);
epicsShareFunc char * /* expanded string; NULL if any undefined macros */
/**
* \brief Expands macros and environment variables in a string.
* \return Expanded string; NULL if any undefined macros were used.
*
* This routine is similar to macEnvExpand() but allows an optional handle
* to be passed in that may contain additional macro definitions.
* These macros are appended to the set of macros from environment
* variables when expanding the string.
*/
epicsShareFunc char *
epicsShareAPI macDefExpand(
const char *str, /* string to be expanded */
MAC_HANDLE *macros /* opaque handle; can be NULL if default */
/* special characters are to be used */
const char *str, /**< string to be expanded */
MAC_HANDLE *macros /**< opaque handle; may be NULL if only
environment variables are to be used */
);
/** @} */
#ifdef __cplusplus
}

View File

@@ -5,9 +5,15 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* src/libCom/adjustment.h */
/**
* \file adjustment.h
* \brief Declare function `adjustToWorstCaseAlignment`
*
* Declares a single function `adjustToWorstCaseAlignment`.
*/
#ifndef INCadjustmenth
#define INCadjustmenth
@@ -17,6 +23,9 @@
extern "C" {
#endif
/** returns a value larger or equal than `size`, that is an exact
multiple of the worst case alignment for the architecture on
which the routine is executed. */
epicsShareFunc size_t adjustToWorstCaseAlignment(size_t size);
#ifdef __cplusplus
@@ -25,4 +34,3 @@ epicsShareFunc size_t adjustToWorstCaseAlignment(size_t size);
#endif /*INCadjustmenth*/

View File

@@ -4,13 +4,17 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Alarm definitions, must match menuAlarmSevr.dbd and menuAlarmStat.dbd */
/*
* Authors: Bob Dalesio and Marty Kraimer
* Date: 11-7-90
/**
* \file alarm.h
* \brief Alarm severity and status/condition values
* \author Bob Dalesio and Marty Kraimer
*
* These alarm definitions must match the related
* menuAlarmSevr.dbd and menuAlarmStat.dbd files
* found in the IOC database module.
*/
#ifndef INC_alarm_H
@@ -22,54 +26,68 @@
extern "C" {
#endif
/**
* \brief The NO_ALARM value can be used as both a severity and a status.
*/
#define NO_ALARM 0
/* ALARM SEVERITIES - must match menuAlarmSevr.dbd */
/**
* \brief Alarm severity values
* \note These must match the choices in menuAlarmSevr.dbd
*/
typedef enum {
epicsSevNone = NO_ALARM,
epicsSevMinor,
epicsSevMajor,
epicsSevInvalid,
ALARM_NSEV
epicsSevNone = NO_ALARM, /**< No alarm */
epicsSevMinor, /**< Minor alarm severity */
epicsSevMajor, /**< Major alarm severity */
epicsSevInvalid, /**< Invalid alarm severity */
ALARM_NSEV /**< Number of alarm severities */
} epicsAlarmSeverity;
/**
* \name Original macros for alarm severity values
* @{
*/
#define firstEpicsAlarmSev epicsSevNone
#define MINOR_ALARM epicsSevMinor
#define MAJOR_ALARM epicsSevMajor
#define INVALID_ALARM epicsSevInvalid
#define lastEpicsAlarmSev epicsSevInvalid
/** @} */
/* ALARM STATUS - must match menuAlarmStat.dbd */
/**
* \brief Alarm status/condition values
* \note These must match the choices in menuAlarmStat.dbd
*/
typedef enum {
epicsAlarmNone = NO_ALARM,
epicsAlarmRead,
epicsAlarmWrite,
epicsAlarmHiHi,
epicsAlarmHigh,
epicsAlarmLoLo,
epicsAlarmLow,
epicsAlarmState,
epicsAlarmCos,
epicsAlarmComm,
epicsAlarmTimeout,
epicsAlarmHwLimit,
epicsAlarmCalc,
epicsAlarmScan,
epicsAlarmLink,
epicsAlarmSoft,
epicsAlarmBadSub,
epicsAlarmUDF,
epicsAlarmDisable,
epicsAlarmSimm,
epicsAlarmReadAccess,
epicsAlarmWriteAccess,
ALARM_NSTATUS
epicsAlarmNone = NO_ALARM, /**< No alarm */
epicsAlarmRead, /**< Read alarm (read error) */
epicsAlarmWrite, /**< Write alarm (write error) */
epicsAlarmHiHi, /**< High high limit alarm */
epicsAlarmHigh, /**< High limit alarm */
epicsAlarmLoLo, /**< Low low limit alarm */
epicsAlarmLow, /**< Low limit alarm */
epicsAlarmState, /**< State alarm (e.g. off/on) */
epicsAlarmCos, /**< Change of state alarm */
epicsAlarmComm, /**< Communication alarm */
epicsAlarmTimeout, /**< Timeout alarm */
epicsAlarmHwLimit, /**< Hardware limit alarm */
epicsAlarmCalc, /**< Calculation expression error */
epicsAlarmScan, /**< Scan alarm, e.g. record not processed (10 times) or not in desired scan list */
epicsAlarmLink, /**< Link alarm */
epicsAlarmSoft, /**< Soft alarm, e.g. in sub record if subroutine gives error */
epicsAlarmBadSub, /**< Bad subroutine alarm, e.g. in sub record subroutine not defined */
epicsAlarmUDF, /**< Undefined value alarm, e.g. record never processed */
epicsAlarmDisable, /**< Record disabled using DISV/DISA fields */
epicsAlarmSimm, /**< Record is in simulation mode */
epicsAlarmReadAccess, /**< Read access permission problem */
epicsAlarmWriteAccess, /**< Write access permission problem */
ALARM_NSTATUS /**< Number of alarm conditions */
} epicsAlarmCondition;
/**
* \name Original macros for alarm status/condition values
* @{
*/
#define firstEpicsAlarmCond epicsAlarmNone
#define READ_ALARM epicsAlarmRead
#define WRITE_ALARM epicsAlarmWrite
@@ -93,11 +111,15 @@ typedef enum {
#define READ_ACCESS_ALARM epicsAlarmReadAccess
#define WRITE_ACCESS_ALARM epicsAlarmWriteAccess
#define lastEpicsAlarmCond epicsAlarmWriteAccess
/** @} */
/* Name string arrays */
/**
* \brief How to convert an alarm severity into a string
*/
epicsShareExtern const char *epicsAlarmSeverityStrings [ALARM_NSEV];
/**
* \brief How to convert an alarm condition/status into a string
*/
epicsShareExtern const char *epicsAlarmConditionStrings [ALARM_NSTATUS];

View File

@@ -4,13 +4,16 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* This file is deprecated, use alarm.h instead.
/**
* \file alarmString.h
* \brief Deprecated, use alarm.h instead
*
* Old string names for alarm status and severity values
* How to convert alarm status and severity values into a string for printing.
*
* \note This file is deprecated, use alarm.h instead.
*/
#ifndef INC_alarmString_H
@@ -22,9 +25,13 @@
extern "C" {
#endif
/* Old versions of alarmString.h defined these names: */
/**
* \brief An alias for epicsAlarmSeverityStrings
*/
#define alarmSeverityString epicsAlarmSeverityStrings
/**
* \brief An alias for epicsAlarmConditionStrings
*/
#define alarmStatusString epicsAlarmConditionStrings

View File

@@ -4,8 +4,23 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**
* \file cantProceed.h
* \brief Routines for code that can't continue or return after an error.
*
* This is the EPICS equivalent of a Kernel Panic, except that the effect
* is to halt only the thread that detects the error.
*/
/* callocMustSucceed() and mallocMustSucceed() can be
* used in place of calloc() and malloc(). If size or count are zero, or the
* memory allocation fails, they output a message and call cantProceed().
*/
#ifndef INCcantProceedh
#define INCcantProceedh
@@ -18,9 +33,42 @@
extern "C" {
#endif
epicsShareFunc void cantProceed(const char *errorMessage, ...) EPICS_PRINTF_STYLE(1,2);
epicsShareFunc void * callocMustSucceed(size_t count, size_t size, const char *errorMessage);
/** \brief Suspend this thread, the caller cannot continue or return.
*
* The effect of calling this is to print the error message followed by
* the name of the thread that is being suspended. A stack trace will
* also be shown if supported by the OS, and the thread is suspended
* inside an infinite loop.
* \param errorMessage A printf-style error message describing the error.
* \param ... Any parameters required for the error message.
*/
epicsShareFunc void cantProceed(const char *errorMessage, ...)
EPICS_PRINTF_STYLE(1,2);
/** \name Memory Allocation Functions
* These versions of calloc() and malloc() never fail, they suspend the
* thread if the OS is unable to allocate the requested memory at the current
* time. If the thread is resumed, they will re-try the memory allocation,
* and will only return after it succeeds. These routines should only be used
* while an IOC is starting up; code that runs after iocInit() should fail
* gracefully when memory runs out.
*/
/** @{ */
/** \brief A calloc() that never returns NULL.
* \param count Number of objects.
* \param size Size of each object.
* \param errorMessage What this memory is needed for.
* \return Pointer to zeroed allocated memory.
*/
epicsShareFunc void * callocMustSucceed(size_t count, size_t size,
const char *errorMessage);
/** \brief A malloc() that never returns NULL.
* \param size Size of block to allocate.
* \param errorMessage What this memory is needed for.
* \return Pointer to allocated memory.
*/
epicsShareFunc void * mallocMustSucceed(size_t size, const char *errorMessage);
/** @} */
#ifdef __cplusplus
}

View File

@@ -4,11 +4,16 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Marty Kraimer
* Date: 6-1-90
/**
* \file dbDefs.h
* \author Marty Kraimer
*
* \brief Miscellaneous macro definitions.
*
* This file defines several miscellaneous macros.
*/
#ifndef INC_dbDefs_H
@@ -26,22 +31,31 @@
#endif
#define FALSE 0
/* deprecated, use static */
/** \brief Deprecated synonym for \c static */
#ifndef LOCAL
# define LOCAL static
#endif
/* number of elements in an array */
/** \brief Number of elements in array */
#ifndef NELEMENTS
# define NELEMENTS(array) (sizeof (array) / sizeof ((array) [0]))
#endif
/* byte offset of member in structure - deprecated, use offsetof */
/** \brief Deprecated synonym for \c offsetof */
#ifndef OFFSET
# define OFFSET(structure, member) offsetof(structure, member)
#endif
/* Subtract member byte offset, returning pointer to parent object */
/** \brief Find parent object from a member pointer
*
* Subtracts the byte offset of the member in the structure from the
* pointer to the member itself, giving a pointer to parent strucure.
* \param ptr Pointer to a member data field of a structure
* \param structure Type name of the parent structure
* \param member Field name of the data member
* \return Pointer to the parent structure
* \note Both GCC and Clang will type-check this macro.
*/
#ifndef CONTAINER
# ifdef __GNUC__
# define CONTAINER(ptr, structure, member) ({ \
@@ -54,15 +68,18 @@
# endif
#endif
/*Process Variable Name Size */
/* PVNAME_STRINGSZ includes the nil terminator */
/** \brief Size of a record name including the nil terminator */
#define PVNAME_STRINGSZ 61
/** \brief Size of a record name without the nil terminator */
#define PVNAME_SZ (PVNAME_STRINGSZ - 1)
/* Buffer size for the string representation of a DBF_*LINK field */
/**
* \def PVLINK_STRINGSZ
* \brief Buffer size for the string representation of a DBF_*LINK field
*/
#define PVLINK_STRINGSZ 1024
/* dbAccess enums/menus can have up to this many choices */
/** \brief dbAccess enums/menus can have up to this many choices */
#define DB_MAX_CHOICES 30
#endif /* INC_dbDefs_H */

View File

@@ -7,6 +7,18 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*epicsExit.h*/
/**
* \file epicsExit.h
*
* \brief Extended replacement for the Posix exit and atexit routines.
*
* This is an extended replacement for the Posix exit and atexit routines, which
* also provides a pointer argument to pass to the exit handlers. This facility
* was created because of problems on vxWorks and windows with the implementation
* of atexit, i.e. neither of these systems implement exit and atexit according
* to the POSIX standard.
*/
#ifndef epicsExith
#define epicsExith
#include <shareLib.h>
@@ -15,15 +27,63 @@
extern "C" {
#endif
/**
* \brief Pointer to a callback function that is to be called
* by the epicsExit subsystem.
*/
typedef void (*epicsExitFunc)(void *arg);
/**
* \brief Calls epicsExitCallAtExits(), then the OS exit() routine.
* \param status Passed to exit()
*/
epicsShareFunc void epicsExit(int status);
/**
* \brief Arrange to call epicsExit() later from a low priority thread.
*
* This delays the actual call to exit() so it doesn't run in this thread.
* \param status Passed to exit()
*/
epicsShareFunc void epicsExitLater(int status);
/**
* \brief Internal routine that runs the registered exit routines.
*
* Calls each of the functions registered by prior calls to epicsAtExit
* in reverse order of their registration.
* \note Most applications will not call this routine directly.
*/
epicsShareFunc void epicsExitCallAtExits(void);
/**
* \brief Register a function and an associated context parameter
* \param func Function to be called when epicsExitCallAtExits is invoked.
* \param arg Context parameter for the function.
* \param name Function name
*/
epicsShareFunc int epicsAtExit3(epicsExitFunc func, void *arg, const char* name);
#define epicsAtExit(F,A) epicsAtExit3(F,A,#F)
/**
* \brief Convenience macro to register a function and context value to be
* run when the process exits.
* \param F Function to be called at process shutdown.
* \param A Context parameter for the function.
*/
#define epicsAtExit(F,A) epicsAtExit3(F,A,#F)
/**
* \brief Internal routine that runs the registered thread exit routines.
*
* Calls each of the functions that were registered in the current thread by
* calling epicsAtThreadExit(), in reverse order of their registration.
* \note This routine is called automatically when an epicsThread's main
* entry routine returns. It will not be run if the thread gets stopped by
* some other method.
*/
epicsShareFunc void epicsExitCallAtThreadExits(void);
/**
* \brief Register a function and an context value to be run by this thread
* when it returns from its entry routine.
* \param func Function be called at thread completion.
* \param arg Context parameter for the function.
*/
epicsShareFunc int epicsAtThreadExit(epicsExitFunc func, void *arg);

View File

@@ -1,5 +1,3 @@
/*epicsExport.h */
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
@@ -7,37 +5,122 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef INCepicsExporth
#define INCepicsExporth
#ifndef INC_epicsExport_H
#define INC_epicsExport_H
/** \file epicsExport.h
* \brief Exporting IOC objects.
*
* This header is unique, as it defines epicsExportSharedSymbols and thus
* triggers a transition between importing declarations from other libraries,
* to exporting symbols from our own library. The comments in shareLib.h
* provide more information.
*
* This header should be included with a trailing comment to make it stand
* out from other includes, something like this:
\code
#include <epicsExport.h> // defines epicsExportSharedSymbols
\endcode
*/
#define epicsExportSharedSymbols
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define epicsExportSharedSymbols
#include <shareLib.h>
typedef void (*REGISTRAR)(void);
#define EPICS_EXPORT_POBJ(typ,obj) pvar_ ## typ ## _ ## obj
#define EPICS_EXPORT_PFUNC(obj) pvar_func_ ## obj
/** \brief Generate a name for an export object.
* \param typ Object's data type.
* \param obj Object's name.
* \return C identifier for the export object.
*/
#define EPICS_EXPORT_POBJ(typ, obj) pvar_ ## typ ## _ ## obj
#define epicsExportAddress(typ,obj) \
epicsShareExtern typ *EPICS_EXPORT_POBJ(typ,obj); \
epicsShareDef typ *EPICS_EXPORT_POBJ(typ,obj) = (typ *)(char *)&obj
/** \brief Generate a name for an export function object.
* \param fun Function's name.
* \return C identifier for the export object.
*/
#define EPICS_EXPORT_PFUNC(fun) EPICS_EXPORT_POBJ(func, fun)
#define epicsExportRegistrar(func) \
epicsShareFunc REGISTRAR EPICS_EXPORT_PFUNC(func) = (REGISTRAR)(void*)&func
/** \brief Declare an object for exporting.
*
* The epicsExportAddress() macro must be used to declare any IOC object
* that is also named in a DBD file. For example a record support source
* file must contain a statement like:
\code
epicsExportAddress(rset, myRSET);
\endcode
*
* A device support source file must contain a statement like:
\code
epicsExportAddress(dset, devMyName);
\endcode
* Note that the \p typ parameter for a device support entry table must be
* spelled \c dset even if the \p obj was actually declared as some other
* type, say using \c typed_dset .
*
* A driver support source file must contain a statement like:
\code
epicsExportAddress(drvet, drvName);
\endcode
*
* A variable named in a DBD \c variable statement must be declared with:
\code
int myDebug = 0;
epicsExportAddress(int, myDebug);
\endcode
* Only \c int and \c double are currently supported for DBD variables.
*
* \param typ Object's data type.
* \param obj Object's name.
*/
#define epicsExportAddress(typ, obj) \
epicsShareExtern typ *EPICS_EXPORT_POBJ(typ,obj); \
epicsShareDef typ *EPICS_EXPORT_POBJ(typ, obj) = (typ *) (char *) &obj
#define epicsRegisterFunction(func) \
static void register_func_ ## func(void) { \
registryFunctionAdd(#func,(REGISTRYFUNCTION)func);} \
epicsExportRegistrar(register_func_ ## func)
/** \brief Declare a registrar function for exporting.
*
* The epicsExportRegistrar() macro must be used to declare a registrar
* function that is named in a DBD \c registrar statement. For example:
\code
static void myRegistrar(void) {
...
}
epicsExportRegistrar(myRegistrar);
\endcode
*
* \param fun Registrar function's name.
*/
#define epicsExportRegistrar(fun) \
epicsShareFunc REGISTRAR EPICS_EXPORT_PFUNC(fun) = (REGISTRAR) &fun
/** \brief Declare and register a function for exporting.
*
* The epicsRegisterFunction() macro must be used to declare and register
* a function that is named in a DBD \c function statement and called by
* one or more subroutine or aSub records. For example:
\code
epicsRegisterFunction(mySubInit);
epicsRegisterFunction(mySubProcess);
\endcode
*
* \param fun Function's name
*/
#define epicsRegisterFunction(fun) \
static void register_func_ ## fun(void) \
{ \
registryFunctionAdd(#fun, (REGISTRYFUNCTION) fun); \
} \
epicsExportRegistrar(register_func_ ## fun)
#ifdef __cplusplus
}
#endif
#endif /* epicsExporth */
#endif /* INC_epicsExport_H */

View File

@@ -5,8 +5,142 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Andrew Johnson
/**
* \file epicsUnitTest.h
* \brief Unit test routines
* \author Andrew Johnson
*
* The unit test routines make it easy for a test program to generate output
* that is compatible with the Test Anything Protocol and can thus be used with
* Perl's automated Test::Harness as well as generating human-readable output.
* The routines detect whether they are being run automatically and print a
* summary of the results at the end if not.
* A test program starts with a call to testPlan(), announcing how many tests
* are to be conducted. If this number is not known a value of zero can be
* used during development, but it is recommended that the correct value be
* substituted after the test program has been completed.
*
* Individual test results are reported using any of testOk(), testOk1(),
* testOkV(), testPass() or testFail(). The testOk() call takes and also
* returns a logical pass/fail result (zero means failure, any other value
* is success) and a printf-like format string and arguments which describe
* the test. The convenience macro testOk1() is provided which stringifies its
* single condition argument, reducing the effort needed when writing test
* programs. The individual testPass() and testFail() routines can be used when
* the test program takes a different path on success than on failure, but one
* or other must always be called for any particular test. The testOkV() routine
* is a varargs form of testOk() included for internal purposes which may prove
* useful in some cases.
*
* If some program condition or failure makes it impossible to run some tests,
* the testSkip() routine can be used to indicate how many tests are being omitted
* from the run, thus keeping the test counts correct; the constant string why is
* displayed as an explanation to the user (this string is not printf-like).
*
* If some tests are expected to fail because functionality in the module under
* test has not yet been fully implemented, these tests may still be executed,
* wrapped between calls to testTodoBegin() and testTodoEnd(). testTodoBegin()
* takes a constant string indicating why these tests are not expected to
* succeed. This modifies the counting of the results so the wrapped tests will not
* be recorded as failures.
*
* Additional information can be supplied using the testDiag() routine, which
* displays the relevent information as a comment in the result output. None of
* the printable strings passed to any testXxx() routine should contain a newline
* '\n' character, newlines will be added by the test routines as part of the
* Test Anything Protocol. For multiple lines of diagnostic output, call
* testDiag() as many times as necessary.
*
* If at any time the test program is unable to continue for some catastrophic
* reason, calling testAbort() with an appropriate message will ensure that the
* test harness understands this. testAbort() does not return, but calls the ANSI
* C routine abort() to cause the program to stop immediately.
*
* After all of the tests have been completed, the return value from
* testDone() can be used as the return status code from the program's main()
* routine.
*
* On vxWorks and RTEMS, an alternative test harness can be used to run a
* series of tests in order and summarize the results from them all at the end
* just like the Perl harness does. The routine testHarness() is called once at
* the beginning of the test harness program. Each test program is run by
* passing its main routine name to the runTest() macro which expands into a call
* to the runTestFunc() routine. The last test program or the harness program
* itself must finish by calling testHarnessDone() which triggers the summary
* mechanism to generate its result outputs (from an epicsAtExit() callback
* routine).
*
* ### IOC Testing
*
* Some tests require the context of an IOC to be run. This conflicts with the
* idea of running multiple tests within a test harness, as iocInit() is only
* allowed to be called once, and some parts of the full IOC (e.g. the rsrv CA
* server) can not be shut down cleanly. The function iocBuildIsolated() allows
* to start an IOC without its Channel Access parts, so that it can be shutdown
* quite cleanly using iocShutdown(). This feature is only intended to be used
* from test programs, do not use it on productional IOCs. After building the
* IOC using iocBuildIsolated() or iocBuild(), it has to be started by calling
* iocRun(). The suggested call sequence in a test program that needs to run the
* IOC without Channel Access is:
\code
#include "iocInit.h"
MAIN(iocTest)
{
iocBuildIsolated() || iocRun();
... test code ...
iocShutdown();
dbFreeBase(pdbbase);
registryFree();
pdbbase = NULL;
return testDone();
}
\endcode
* The part from iocBuildIsolated() to iocShutdown() can be repeated to
* execute multiple tests within one executable or harness.
*
* To make it easier to create a single test program that can be built for
* both the embedded and workstation operating system harnesses, the header file
* testMain.h provides a convenience macro MAIN() that adjusts the name of the
* test program according to the platform it is running on: main() on
* workstations and a regular function name on embedded systems.
*
* ### Example
*
* The following is a simple example of a test program using the epicsUnitTest
* routines:
\code
#include <math.h>
#include "epicsUnitTest.h"
#include "testMain.h"
MAIN(mathTest)
{
testPlan(3);
testOk(sin(0.0) == 0.0, "Sine starts");
testOk(cos(0.0) == 1.0, "Cosine continues");
if (!testOk1(M_PI == 4.0*atan(1.0)))
testDiag("4 * atan(1) = %g", 4.0 * atan(1.0));
return testDone();
}
\endcode
* The output from running the above program looks like this:
\code
1..3
ok 1 - Sine starts
ok 2 - Cosine continues
ok 3 - M_PI == 4.0*atan(1.0)
Results
=======
Tests: 3
Passed: 3 = 100%
\endcode
*/
#ifndef INC_epicsUnitTest_H
@@ -21,35 +155,111 @@
extern "C" {
#endif
/** \brief Declare the test plan, required.
* \param tests Number of tests to be run. May be zero if not known but the
* test harness then can't tell if the program dies prematurely.
*/
epicsShareFunc void testPlan(int tests);
epicsShareFunc int testOkV(int pass, const char *fmt, va_list pvar);
epicsShareFunc int testOk(int pass, const char *fmt, ...)
EPICS_PRINTF_STYLE(2, 3);
epicsShareFunc void testPass(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
epicsShareFunc void testFail(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
epicsShareFunc void testSkip(int skip, const char *why);
epicsShareFunc void testTodoBegin(const char *why);
epicsShareFunc void testTodoEnd(void);
epicsShareFunc int testDiag(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
epicsShareFunc void testAbort(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
epicsShareFunc int testDone(void);
/** \name Announcing Test Results
* Routines that declare individual test results.
*/
/** @{ */
/** \brief Test result with printf-style description.
* \param pass True/False value indicating result.
* \param fmt A printf-style format string describing the test.
* \param ... Any parameters required for the format string.
* \return The value of \p pass.
*/
epicsShareFunc int testOk(int pass, const char *fmt, ...)
EPICS_PRINTF_STYLE(2, 3);
/** \brief Test result using condition as description
* \param cond Condition to be evaluated and displayed.
* \return The value of \p cond.
*/
#define testOk1(cond) testOk(cond, "%s", #cond)
/** \brief Test result with var-args description.
* \param pass True/False value indicating result.
* \param fmt A printf-style format string describing the test.
* \param pvar A var-args pointer to any parameters for the format string.
* \return The value of \p pass.
*/
epicsShareFunc int testOkV(int pass, const char *fmt, va_list pvar);
/** \brief Passing test result with printf-style description.
* \param fmt A printf-style format string describing the test.
* \param ... Any parameters required for the format string.
* \return The value of \p pass.
*/
epicsShareFunc void testPass(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
/** \brief Failing test result with printf-style description.
* \param fmt A printf-style format string describing the test.
* \param ... Any parameters required for the format string.
*/
epicsShareFunc void testFail(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
/** @} */
/** \name Missing or Failing Tests
* \brief Routines for handling special situations.
*/
/** @{ */
/** \brief Place-holders for tests that can't be run.
* \param skip How many tests are being skipped.
* \param why Reason for skipping these tests.
*/
epicsShareFunc void testSkip(int skip, const char *why);
/** \brief Mark the start of a group of tests that are expected to fail
* \param why Reason for expected failures.
*/
epicsShareFunc void testTodoBegin(const char *why);
/** \brief Mark the end of a failing test group.
*/
epicsShareFunc void testTodoEnd(void);
/** \brief Stop testing, program cannot continue.
* \param fmt A printf-style format string giving the reason for stopping.
* \param ... Any parameters required for the format string.
*/
epicsShareFunc void testAbort(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
/** @} */
/** \brief Output additional diagnostics
* \param fmt A printf-style format string containing diagnostic information.
* \param ... Any parameters required for the format string.
*/
epicsShareFunc int testDiag(const char *fmt, ...)
EPICS_PRINTF_STYLE(1, 2);
/** \brief Mark the end of testing.
*/
epicsShareFunc int testDone(void);
epicsShareFunc
int testImpreciseTiming(void);
/** \name Test Harness for Embedded OSs
* These routines are used to create a test-harness that can run
* multiple test programs, collect their names and results, then
* display a summary at the end of testing.
*/
/** @{ */
typedef int (*TESTFUNC)(void);
/** \brief Initialize test harness
*/
epicsShareFunc void testHarness(void);
epicsShareFunc void testHarnessExit(void *dummy);
epicsShareFunc void runTestFunc(const char *name, TESTFUNC func);
/** \brief Run a test program
* \param func Name of the test program.
*/
#define runTest(func) runTestFunc(#func, func)
/** \brief Declare all test programs finished
*/
#define testHarnessDone() testHarnessExit(0)
/** @} */
#ifdef __cplusplus
}

View File

@@ -4,38 +4,48 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Compiler specific key words to set up external symbols and entry points
/**
* \file shareLib.h
* \brief Mark external symbols and entry points for shared libraries.
*
* This is the header file for the "decorated names" that appear in
* header files, e.g.
*
* #define epicsExportSharedSymbols
* epicsShareFunc int epicsShareAPI a_func(int arg);
*
* These are needed to properly create DLLs on MS Windows.
*
* ### USAGE
*
* USAGE:
* There are two distinct classes of keywords in this file:
*
* 1) epicsShareAPI - specifies a multi-language calling mechanism. On windows
* -# epicsShareAPI - specifies a multi-language calling mechanism. On windows
* this is the pascal calling convention which is used by visual basic and other
* high level tools. This is only necessary if a C/C++ function needs to be called
* from other languages or from high level tools. The epicsShareAPI keyword
* must be present between the function's returned data type and the function's
* name. All compilers targeting windows accept the __stdcall keyword in this
* must be present between the function's returned data type and the function's
* name. All compilers targeting windows accept the __stdcall keyword in this
* location. Functions with variable argument lists should not use the epicsShareAPI
* keyword because __stdcall (pascal) calling convention cannot support variable
* length ed argument lists.
*
* int epicsShareAPI myExtFunc ( int arg );
* int epicsShareAPI myExtFunc ( int arg ) {}
* int epicsShareAPI myExtFunc ( int arg );
* int epicsShareAPI myExtFunc ( int arg ) {}
*
* ** NOTE ** The epicsShareAPI attribute is deprecated and has been removed
* \note The epicsShareAPI attribute is deprecated and has been removed
* from all IOC-specific APIs. Most libCom APIs still use it, but
* it may get removed from these at some point in the future.
*
* 2) epicsShare{Func,Class,Extern,Def} - specifies shareable library (DLL)
* export/import related information in the source code. On windows these keywords
* allow faster dispatching of calls to DLLs because more is known at compile time.
* -# epicsShare{Func,Class,Extern,Def} - specifies shareable library (DLL)
* export/import related information in the source code. On windows these keywords
* allow faster dispatching of calls to DLLs because more is known at compile time.
* It is also not necessary to maintain a linker input files specifying the DLL
* entry points. This maintenance can be more laborious with C++ decorated symbol
* names. These keywords are only necessary if the address of a function or data
* internal to a shareable library (DLL) needs to be visible outside of this shareable
* entry points. This maintenance can be more laborious with C++ decorated symbol
* names. These keywords are only necessary if the address of a function or data
* internal to a shareable library (DLL) needs to be visible outside of this shareable
* library (DLL). All compilers targeting windows accept the __declspec(dllexport)
* and __declspec(dllimport) keywords. For GCC version 4 and above the first three
* keywords specify a visibility attribute of "default", which marks the symbol as
@@ -43,23 +53,23 @@
* significantly reduce the number of symbols exported to a shared library. See the
* URL below for more information.
*
* In header files declare references to externally visible variables, classes and
* In header files declare references to externally visible variables, classes and
* functions like this:
*
* #include "shareLib.h"
* epicsShareFunc int myExtFunc ( int arg );
* epicsShareExtern int myExtVar;
* class epicsShareClass myClass { int func ( void ); };
* #include "shareLib.h"
* epicsShareFunc int myExtFunc ( int arg );
* epicsShareExtern int myExtVar;
* class epicsShareClass myClass { int func ( void ); };
*
* In the implementation file, however, you write:
*
* #include <interfaces_imported_from_other_shareable_libraries.h>
* #define epicsExportSharedSymbols
* #include <interfaces_implemented_in_this_shareable_library.h>
* #include <interfaces_imported_from_other_shareable_libraries.h>
* #define epicsExportSharedSymbols
* #include <interfaces_implemented_in_this_shareable_library.h>
*
* epicsShareDef int myExtVar = 4;
* int myExtFunc ( int arg ) {}
* int myClass::func ( void ) {}
* epicsShareDef int myExtVar = 4;
* int myExtFunc ( int arg ) {}
* int myClass::func ( void ) {}
*
* By default shareLib.h sets the DLL import / export keywords to import from
* a DLL so that, for DLL consumers (users), nothing special must be done. However,
@@ -67,34 +77,42 @@
* which functions are exported from the DLL and which of them are imported
* from other DLLs.
*
* You must first #include what you import and then define epicsExportSharedSymbols
* only right before you #include the prototypes for what you implement! You must
* include shareLib.h again each time that the state of the import/ export keywords
* changes, but this usually occurs as a side effect of including the shareable
* libraries header file(s).
* You must first \c \#include what you import and then \c \#define
* \c epicsExportSharedSymbols only right before you \c \#include the
* prototypes for what you implement! You must include shareLib.h again each
* time that the state of the import/export keywords changes, but this
* usually occurs as a side effect of including the shareable libraries header
* file(s).
*
* Frequently a header file for a shareable library exported interface will
* have some preprocessor switches like this if this header file must also
* ### Deprecated Usage
*
* The construct described below is used in some EPICS header files bit is
* no longer recommended as it makes it difficult to diagnose the incorrect
* inclusion of headers that are the wrong side of an \c epicsExportSharedSymbols
* marker.
*
* Sometimes a header file for a shareable library exported interface will
* have some preprocessor switches like this if this header file must also
* include header files describing interfaces to other shareable libraries.
*
* #ifdef epicsExportSharedSymbols
* # define interfacePDQ_epicsExportSharedSymbols
* # undef epicsExportSharedSymbols
* #endif
* #ifdef epicsExportSharedSymbols
* # define interfacePDQ_epicsExportSharedSymbols
* # undef epicsExportSharedSymbols
* #endif
*
* #include "epicsTypes.h"
* #include "epicsTime.h"
* #include "epicsTypes.h"
* #include "epicsTime.h"
*
* #ifdef interfacePDQ_epicsExportSharedSymbols
* # define epicsExportSharedSymbols
* # include "shareLib.h"
* #endif
* #ifdef interfacePDQ_epicsExportSharedSymbols
* # define epicsExportSharedSymbols
* # include "shareLib.h"
* #endif
*
* epicsShareFunc int myExtFunc ( int arg );
* epicsShareExtern int myExtVar;
* class epicsShareClass myClass {};
* epicsShareFunc int myExtFunc ( int arg );
* epicsShareExtern int myExtVar;
* class epicsShareClass myClass {};
*
* Fortunately, the above is only the concern of library authors and will have no
* Fortunately, the above is only the concern of library authors and will have no
* impact on persons using functions and or external data from a library.
*/
@@ -132,7 +150,7 @@
# define epicsShareFunc
# endif
# endif
# define epicsShareDef
# define epicsShareDef
# define epicsShareAPI __stdcall /* function removes arguments */
# define READONLY const
@@ -162,18 +180,18 @@
*/
#elif defined(VAXC)
/*
/*
* VAXC creates FORTRAN common blocks when
* we use "extern int fred"/"int fred=4". Therefore,
* the initialization is not loaded unless we
* call a function in that object module.
*
* DEC CXX does not have this problem.
* We suspect (but do not know) that DEC C
* We suspect (but do not know) that DEC C
* also does not have this problem.
*/
# define epicsShareExtern globalref
# define epicsShareDef globaldef
# define epicsShareExtern globalref
# define epicsShareDef globaldef
# define READONLY const
# define epicsShareClass
# define epicsShareFunc

View File

@@ -24,13 +24,13 @@ extern "C" {
#define OSI_PATH_SEPARATOR "/"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
\return NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
\return NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);

View File

@@ -7,10 +7,11 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author:
* Jeffrey O. Hill
* johill@lanl.gov
/**
* \file compilerDependencies.h
* \author Jeffrey O. Hill johill@lanl.gov
* \brief Compiler specific declarations
*
*/
#ifndef compilerDependencies_h

View File

@@ -8,93 +8,125 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLib.h */
/*
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
/**
* \file devLib.h
* \brief API for accessing hardware devices, originally over VMEbus
* \author Marty Kraimer and Jeff Hill
*
* Support for allocation of common device resources
*/
#ifndef EPICSDEVLIB_H
#define EPICSDEVLIB_H
/*
* Support macros
*/
/*
* Normalize a digital value and convert it to type TYPE
*
* Ex:
* float f;
* int d;
* f = devNormalizeDigital(d,12)
*
/**
* \name Macros for normalizing values
* \warning Deprecated, we don't know of any code currently using these.
* @{
*/
/** \brief Create a bit mask for a given number of bits */
#define devCreateMask(NBITS) ((1<<(NBITS))-1)
/** \brief Normalize a raw integer value and convert it to type double */
#define devDigToNml(DIGITAL,NBITS) \
(((double)(DIGITAL))/devCreateMask(NBITS))
/** \brief Convert a normalized value to a raw integer */
#define devNmlToDig(NORMAL,NBITS) \
(((long)(NORMAL)) * devCreateMask(NBITS))
/** @} */
/*
*
* Alignment mask
* (for use when testing to see if the proper number of least
* significant bits are zero)
*
/**
* \name Macros for pointer alignment
* \warning Deprecated, we don't know of any code currently using these.
* @{
*/
/** \brief Create an alignment mask for CTYPE */
#define devCreateAlignmentMask(CTYPE)\
(sizeof(CTYPE)>sizeof(double)?sizeof(double)-1:sizeof(CTYPE)-1)
/*
* pointer aligned test
* (returns true if the pointer is on the worst case alignemnt
* boundary for its type)
/** \brief Check Pointer alignment, returns true if the pointer \c PTR
* is suitably aligned for its data type
*/
#define devPtrAlignTest(PTR) (!(devCreateAlignmentMask(*PTR)&(long)(PTR)))
/** @} */
/*
* error codes (and messages) associated with devLib.c
/**
* \name Error status values returned by devLib routines
* @{
*/
#define S_dev_success 0
#define S_dev_vectorInUse (M_devLib| 1) /*interrupt vector in use*/
#define S_dev_vecInstlFail (M_devLib| 2) /*interrupt vector install failed*/
#define S_dev_uknIntType (M_devLib| 3) /*Unrecognized interrupt type*/
/** \brief Interrupt vector in use */
#define S_dev_vectorInUse (M_devLib| 1) /*Interrupt vector in use*/
/** \brief Interrupt vector install failed */
#define S_dev_vecInstlFail (M_devLib| 2) /*Interrupt vector install failed*/
/** \brief Unrecognized interrupt type */
#define S_dev_uknIntType (M_devLib| 3) /*Unrecognized interrupt type*/
/** \brief Interrupt vector not in use by caller */
#define S_dev_vectorNotInUse (M_devLib| 4) /*Interrupt vector not in use by caller*/
/** \brief Invalid VME A16 address */
#define S_dev_badA16 (M_devLib| 5) /*Invalid VME A16 address*/
/** \brief Invalid VME A24 address */
#define S_dev_badA24 (M_devLib| 6) /*Invalid VME A24 address*/
/** \brief Invalid VME A32 address */
#define S_dev_badA32 (M_devLib| 7) /*Invalid VME A32 address*/
/** \brief Unrecognized address space type */
#define S_dev_uknAddrType (M_devLib| 8) /*Unrecognized address space type*/
#define S_dev_addressOverlap (M_devLib| 9) /*Specified device address overlaps another device*/
#define S_dev_identifyOverlap (M_devLib| 10) /*This device already owns the address range*/
#define S_dev_addrMapFail (M_devLib| 11) /*unable to map address*/
#define S_dev_intDisconnect (M_devLib| 12) /*Interrupt at vector disconnected from an EPICS device*/
#define S_dev_internal (M_devLib| 13) /*Internal failure*/
#define S_dev_intEnFail (M_devLib| 14) /*unable to enable interrupt level*/
#define S_dev_intDissFail (M_devLib| 15) /*unable to disable interrupt level*/
#define S_dev_noMemory (M_devLib| 16) /*Memory allocation failed*/
#define S_dev_addressNotFound (M_devLib| 17) /*Specified device address unregistered*/
/** \brief Specified device address overlaps another device */
#define S_dev_addressOverlap (M_devLib| 9) /*Specified device address overlaps another device*/
/** \brief This device already owns the address range */
#define S_dev_identifyOverlap (M_devLib| 10) /*This device already owns the address range*/
/** \brief Unable to map address */
#define S_dev_addrMapFail (M_devLib| 11) /*Unable to map address*/
/** \brief Interrupt at vector disconnected from an EPICS device */
#define S_dev_intDisconnect (M_devLib| 12) /*Interrupt at vector disconnected from an EPICS device*/
/** \brief Internal failure */
#define S_dev_internal (M_devLib| 13) /*Internal failure*/
/** \brief Unable to enable interrupt level */
#define S_dev_intEnFail (M_devLib| 14) /*Unable to enable interrupt level*/
/** \brief Unable to disable interrupt level */
#define S_dev_intDissFail (M_devLib| 15) /*Unable to disable interrupt level*/
/** \brief Memory allocation failed */
#define S_dev_noMemory (M_devLib| 16) /*Memory allocation failed*/
/** \brief Specified device address unregistered */
#define S_dev_addressNotFound (M_devLib| 17) /*Specified device address unregistered*/
/** \brief No device at specified address */
#define S_dev_noDevice (M_devLib| 18) /*No device at specified address*/
/** \brief Wrong device type found at specified address */
#define S_dev_wrongDevice (M_devLib| 19) /*Wrong device type found at specified address*/
/** \brief Signal number (offset) to large */
#define S_dev_badSignalNumber (M_devLib| 20) /*Signal number (offset) to large*/
/** \brief Signal count to large */
#define S_dev_badSignalCount (M_devLib| 21) /*Signal count to large*/
/** \brief Device does not support requested operation */
#define S_dev_badRequest (M_devLib| 22) /*Device does not support requested operation*/
#define S_dev_highValue (M_devLib| 23) /*Parameter to high*/
#define S_dev_lowValue (M_devLib| 24) /*Parameter to low*/
/** \brief Parameter too high */
#define S_dev_highValue (M_devLib| 23) /*Parameter too high*/
/** \brief Parameter too low */
#define S_dev_lowValue (M_devLib| 24) /*Parameter too low*/
/** \brief Specified address is ambiguous (more than one device responds) */
#define S_dev_multDevice (M_devLib| 25) /*Specified address is ambiguous (more than one device responds)*/
/** \brief Device self test failed */
#define S_dev_badSelfTest (M_devLib| 26) /*Device self test failed*/
/** \brief Device failed during initialization */
#define S_dev_badInit (M_devLib| 27) /*Device failed during initialization*/
/** \brief Input exceeds Hardware Limit */
#define S_dev_hdwLimit (M_devLib| 28) /*Input exceeds Hardware Limit*/
/** \brief Unable to locate address space for device */
#define S_dev_deviceDoesNotFit (M_devLib| 29) /*Unable to locate address space for device*/
#define S_dev_deviceTMO (M_devLib| 30) /*device timed out*/
#define S_dev_badFunction (M_devLib| 31) /*bad function pointer*/
#define S_dev_badVector (M_devLib| 32) /*bad interrupt vector*/
#define S_dev_badArgument (M_devLib| 33) /*bad function argument*/
/** \brief Device timed out */
#define S_dev_deviceTMO (M_devLib| 30) /*Device timed out*/
/** \brief Bad function pointer */
#define S_dev_badFunction (M_devLib| 31) /*Bad function pointer*/
/** \brief Bad interrupt vector */
#define S_dev_badVector (M_devLib| 32) /*Bad interrupt vector*/
/** \brief Bad function argument */
#define S_dev_badArgument (M_devLib| 33) /*Bad function argument*/
/** \brief Invalid ISA address */
#define S_dev_badISA (M_devLib| 34) /*Invalid ISA address*/
/** \brief Invalid VME CR/CSR address */
#define S_dev_badCRCSR (M_devLib| 35) /*Invalid VME CR/CSR address*/
/** \brief Synonym for S_dev_intEnFail */
#define S_dev_vxWorksIntEnFail S_dev_intEnFail
/** @} */
#endif /* EPICSDEVLIB_H */

View File

@@ -4,14 +4,23 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLib.h */
/*
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
/**
* \file devLibVME.h
* \author Marty Kraimer, Jeff Hill
* \brief API for accessing hardware devices, mosty over VMEbus.
*
* API for accessing hardware devices. The original APIs here were for
* written for use with VMEbus but additional routines were added for
* ISA-bus (but not fully implemented inside EPICS Base and may never
* have been actually used).
*
* If all VMEbus drivers register with these routines then addressing
* conflicts caused by multiple device/drivers trying to use the same
* VME addresses will be detected. This API also makes it easy for a
* single driver to be written that works on both VxWorks and RTEMS.
*/
#ifndef INCdevLibh
@@ -27,23 +36,17 @@
extern "C" {
#endif
/*
* epdevAddressType & EPICStovxWorksAddrType
* devLib.c must change in unison
*/
/** \brief The available bus address types */
typedef enum {
atVMEA16,
atVMEA24,
atVMEA32,
atISA, /* memory mapped ISA access (until now only on PC) */
atVMECSR, /* VME-64 CR/CSR address space */
atLast /* atLast must be the last enum in this list */
} epicsAddressType;
atVMEA16, /**< \brief VME short I/O. */
atVMEA24, /**< \brief VME standard I/O. */
atVMEA32, /**< \brief VME extended I/O. */
atISA, /**< \brief Memory mapped ISA access. */
atVMECSR, /**< \brief VME-64 CR/CSR address space. */
atLast /**< \brief Invalid, must be the last entry. */
} epicsAddressType;
/*
* pointer to an array of strings for each of
* the above address types
*/
/** \brief A string representation of each of the bus address types */
epicsShareExtern const char *epicsAddressTypeName[];
#ifdef __cplusplus
@@ -61,41 +64,54 @@ epicsShareExtern const char *epicsAddressTypeName[];
extern "C" {
#endif
/*
* General API
/** \brief Print a map of registered bus addresses.
*
* This section applies to all bus types
* Display a table of registsred bus address ranges, including the owner of
* each registered address.
* \return 0, or an error status value
*/
epicsShareFunc long devAddressMap(void);
epicsShareFunc long devAddressMap(void); /* print an address map */
/*
* devBusToLocalAddr()
/** \brief Translate a bus address to a pointer the CPU can use.
*
* OSI routine to translate bus addresses their local CPU address mapping
* Given a bus address, returns a pointer to that location in the CPU's
* memory map, or an error if direct access isn't currently possible.
* \param addrType The bus address type.
* \param busAddr Bus address to be translated.
* \param *ppLocalAddr Where to put the CPU pointer.
* \return 0, or an error status value.
*/
epicsShareFunc long devBusToLocalAddr (
epicsAddressType addrType,
size_t busAddr,
volatile void **ppLocalAddr);
/*
* devReadProbe()
/** \brief Probe the bus for reading from a specific address.
*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
* Performs a bus-error-safe \c wordSize atomic read from a specific
* address and returns an error if this caused a bus error.
* \param wordSize The word size to read: 1, 2, 4 or 8 bytes.
* \param ptr Pointer to the location in the CPU's memory map to read.
* \param pValueRead Where to put the value read.
* \return 0, or an error status value if the location could not be
* accessed or the read caused a bus error.
*/
epicsShareFunc long devReadProbe (
unsigned wordSize, volatile const void *ptr, void *pValueRead);
/*
* devNoResponseProbe()
/** \brief Read-probe a range of bus addresses, looking for empty space.
*
* Verifies that no devices respond at naturally aligned words
* within the specified address range. Return success if no devices
* respond. Returns an error if a device does respond or if
* a physical address for a naturally aligned word cant be mapped.
* Checks all naturally aligned word sizes between char and long for
* the entire specified range of bytes.
* Verifies that no device responds at any naturally aligned addresses
* within the given range. Tries to read every aligned address at every
* word size between char and long over the entire range, returning
* success only if none of the reads succeed.
* \warning This routine may be slow and have a very bad effect on a busy
* VMEbus. Every read probe of an unused address will hold onto the VMEbus
* for the global bus timeout period.
* \param addrType The bus address type.
* \param base First address base to probe.
* \param size Range of bus addresses to test, in bytes.
* \return 0 if no devices respond, or an error status value.
*/
epicsShareFunc long devNoResponseProbe(
epicsAddressType addrType,
@@ -103,29 +119,71 @@ epicsShareFunc long devNoResponseProbe(
size_t size
);
/*
* devWriteProbe
/** \brief Probe the bus for writing to a specific address.
*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
* Performs a bus-error-safe \c wordSize atomic write to a specific
* address and returns an error if this caused a bus error.
* \param wordSize The word size to write: 1, 2, 4 or 8 bytes.
* \param ptr Pointer to the location in the CPU's memory map to write to.
* \param pValueWritten The value to write.
* \return 0, or an error status value if the location could not be
* accessed or the write caused a bus error.
*/
epicsShareFunc long devWriteProbe (
unsigned wordSize, volatile void *ptr, const void *pValueWritten);
/** \brief Register a bus address range with a name.
*
* The devLib code keeps a list of all bus address ranges registered with
* this routine and returns an error if a later call attempts to register
* any addresses that overlap with a range already registered. The call to
* registering a range also converts the given base address into a pointer
* in the CPU address space for the driver to use (see devBusToLocalAddr()).
* \param pOwnerName Name of a driver that will own this range.
* \param addrType The bus address type.
* \param logicalBaseAddress The bus start address.
* \param size Number of bytes to reserve.
* \param pPhysicalAddress Where to put the converted CPU pointer.
* \return 0, or an error status.
*/
epicsShareFunc long devRegisterAddress(
const char *pOwnerName,
epicsAddressType addrType,
size_t logicalBaseAddress,
size_t size, /* bytes */
size_t size,
volatile void **pPhysicalAddress);
/** \brief Release a bus address range previously registered.
*
* Release an address range that was previously registered by a call to
* devRegisterAddress() or devAllocAddress().
* \param addrType The bus address type.
* \param logicalBaseAddress The bus start address.
* \param pOwnerName The name of the driver that owns this range.
* \return 0, or an error status.
*/
epicsShareFunc long devUnregisterAddress(
epicsAddressType addrType,
size_t logicalBaseAddress,
const char *pOwnerName);
/*
* allocate and register an unoccupied address block
/** \brief Allocate and register an unoccupied address block.
*
* Asks devLib 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. As with devRegisterAddress() this call also converts
* the new base address into a pointer in the CPU address space for the
* driver to use (see devBusToLocalAddr()).
* \note This routine calls devNoResponseProbe() to find an unoccupied
* block in the bus address space, so using it may have a bad effect on a
* busy VMEbus at allocation time; see the warning above.
* \param pOwnerName Name of a driver that will own this range.
* \param addrType The bus address type.
* \param size Number of bytes to be allocated.
* \param alignment How many low bits in the address must all be zero.
* \param pLocalAddress Where to put the CPU pointer.
* \return 0, or an error status value.
*/
epicsShareFunc long devAllocAddress(
const char *pOwnerName,
@@ -134,117 +192,185 @@ epicsShareFunc long devAllocAddress(
unsigned alignment, /*n ls bits zero in addr*/
volatile void **pLocalAddress);
/*
* VME API
*
* Functions in this section apply only to the VME bus type
/** \name VME Interrupt Management
* Routines to manage VME interrupts.
* @{
*/
/*
* connect ISR to a VME interrupt vector
/** \brief Connect an ISR up to a VME interrupt vector.
*
* Interrupt Service Routines (ISRs) are normally written in C, and get
* passed a context parameter given with them to this connection routine.
*
* There are many restrictions on the routines that an ISR may call; see
* epicsEvent.h, epicsInterrupt.h, epicsMessageQueue.h, epicsRingBytes.h,
* epicsRingPointer.h and epicsTime.h for some APIs known to be suitable.
* It is safest just to trigger a high-priority task to handle any
* complex work that must happen as a result of the interrupt.
* \param vectorNumber VME interrupt vector number.
* \param pFunction The ISR to be called.
* \param parameter Context parameter for the ISR.
* \return 0, or an error status value.
*/
epicsShareFunc long devConnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *),
void *parameter);
/*
* disconnect ISR from a VME interrupt vector
/** \brief Disconnect 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
* Device drivers may disconnect an ISR they connected earlier using this
* routine. In addition to taking the \c vectorNumber the ISR itself is
* required and used as a check to prevent a driver from inadvertently
* removing an interrupt handler that it didn't install.
*
* On a PowerPC target running VxWorks, this routine will always return
* with an error status.
* \param vectorNumber VME interrupt vector number.
* \param pFunction The ISR to be disconnected.
* \return 0, or an error status value.
*/
epicsShareFunc long devDisconnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *));
/*
* determine if a VME interrupt vector is in use
/** \brief Determine if a VME interrupt vector is in use.
*
* returns boolean
* On a PowerPC target running VxWorks this routine will always return
* false, indicating that a vector is unused.
* \param vectorNumber Interrupt vector number.
* \return True if vector has an ISR attached, otherwise false.
*/
epicsShareFunc int devInterruptInUseVME (unsigned vectorNumber);
/*
* enable VME interrupt level
/** \brief Enable a VME interrupt level onto the CPU.
*
* The VMEbus allows multiple CPU boards to be installed in the same
* backplane. When this is done, the differente VME interrupt levels
* must be assigned to the CPUs since they cannot be shared. This
* routine tells the VME interface that it should connect interrupts
* from the indicated interrupt level to a CPU interrupt line.
* \param level VMEbus interrupt level to enable, 1-7.
* \return 0, or an error status value.
*/
epicsShareFunc long devEnableInterruptLevelVME (unsigned level);
/*
* disable VME interrupt level
/** \brief Disable a VME interrupt level.
*
* This routine is the reverse of devEnableInterruptLevelVME().
* \note This routine should not normally be used, even by a
* driver that enabled the interrupt level. Disabling a VME
* interrupt level should only be done by software that knows
* for certain that no other interrupting device is also using
* that VME interrupt level.
* \param level VMEbus interrupt level to disable, 1-7.
* \return 0, or an error status value.
*/
epicsShareFunc long devDisableInterruptLevelVME (unsigned level);
/** @} */
/*
* Routines to allocate and free memory in the A24 memory region.
*
/** \name Memory for VME DMA Operations
* These routines manage memory that can be directly accessed
* from the VMEbus in the A24 address space by another bus master
* such as a DMA controller.
* @{
*/
/** \brief malloc() for VME drivers that support DMA.
*
* Allocate memory of a given size from a region that can be
* accessed from the VMEbus in the A24 address space.
* \param size How many bytes to allocate
* \return A pointer to the memory allocated, or NULL.
*/
epicsShareFunc void *devLibA24Malloc(size_t size);
/** \brief calloc() for VME drivers that support DMA.
*
* Allocate and zero-fill a block of memory of a given size from
* a region that can be accessed from the VMEbus in the A24
* address space.
* \param size How many bytes to allocate and zero.
* \return A pointer to the memory allocated, or NULL.
*/
epicsShareFunc void *devLibA24Calloc(size_t size);
/** \brief free() for VME drivers that support DMA.
*
* Free a block of memory that was allocated using either
* devLibA24Malloc() or devLibA24Calloc().
* \param pBlock Block to be released.
*/
epicsShareFunc void *devLibA24Malloc(size_t);
epicsShareFunc void *devLibA24Calloc(size_t);
epicsShareFunc void devLibA24Free(void *pBlock);
/** @} */
/*
* ISA API
*
* Functions in this section apply only to the ISA bus type
/** \name ISA Interrupt Management
* Routines to manage ISAbus interrupts.
* \note These routines may not have been used for a very long time;
* some appear to have never been implemented at all. They may vanish
* with no notice from future versions of EPICS Base. Nobody is using
* the PC's ISA-bus any more are they?
* @{
*/
/*
* connect ISR to an ISA interrupt level
* (not implemented)
* (API should be reviewed)
/**
* Connect ISR to a ISA interrupt.
* \warning Not implemented!
* \param interruptLevel Bus interrupt level to connect to.
* \param pFunction C function pointer to connect to.
* \param parameter Parameter to the called function.
* \return Returns success or error.
*/
epicsShareFunc long devConnectInterruptISA(
unsigned interruptLevel,
void (*pFunction)(void *),
void *parameter);
/*
* disconnect ISR from an ISA interrupt level
* (not implemented)
* (API should be reviewed)
*
* 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
/**
* Disconnect ISR from a ISA interrupt level.
* \warning Not implemented!
* \param interruptLevel Interrupt level.
* \param pFunction C function pointer that was connected.
* \return returns success or error.
*/
epicsShareFunc long devDisconnectInterruptISA(
unsigned interruptLevel,
void (*pFunction)(void *));
/*
* determine if an ISA interrupt level is in use
* (not implemented)
*
* returns boolean
/**
* Determine if an ISA interrupt level is in use
* \warning Not implemented!
* \param interruptLevel Interrupt level.
* \return Returns True/False.
*/
epicsShareFunc int devInterruptLevelInUseISA (unsigned interruptLevel);
/*
* enable ISA interrupt level
/**
* Enable ISA interrupt level
* \param level Interrupt level.
* \return Returns True/False.
*/
epicsShareFunc long devEnableInterruptLevelISA (unsigned level);
/*
* disable ISA interrupt level
/**
* Disable ISA interrupt level
* \param level Interrupt level.
* \return Returns True/False.
*/
epicsShareFunc long devDisableInterruptLevelISA (unsigned level);
/*
* Deprecated interface
*/
/** @} */
#ifndef NO_DEVLIB_OLD_INTERFACE
/**
* \name Deprecated Interfaces
* @{
*/
typedef enum {intVME, intVXI, intISA} epicsInterruptType;
/*
* NOTE: this routine has been deprecated. It exists
/**
* \note This routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devConnectInterruptVME, devConnectInterruptPCI,
* devConnectInterruptISA etc. devConnectInterrupt will be removed
* Please use one of devConnectInterruptVME(), devConnectInterruptPCI(),
* devConnectInterruptISA() instead. devConnectInterrupt() will be removed
* in a future release.
*/
epicsShareFunc long devConnectInterrupt(
@@ -253,50 +379,48 @@ epicsShareFunc long devConnectInterrupt(
void (*pFunction)(void *),
void *parameter);
/*
* NOTE: this routine has been deprecated. It exists
/**
* \note This routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devDisconnectInterruptVME, devDisconnectInterruptPCI,
* devDisconnectInterruptISA etc. devDisconnectInterrupt will be removed
* in a future release.
* Please use one of devDisconnectInterruptVME(), devDisconnectInterruptPCI(),
* devDisconnectInterruptISA() instead. devDisconnectInterrupt() will
* be removed in a future release.
*/
epicsShareFunc long devDisconnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)(void *));
/*
* NOTE: this routine has been deprecated. It exists
/**
* \note This routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devEnableInterruptLevelVME, devEnableInterruptLevelPCI,
* devEnableInterruptLevelISA etc. devEnableInterruptLevel will be removed
* in a future release.
* Please use one of devEnableInterruptLevelVME(), devEnableInterruptLevelPCI(),
* devEnableInterruptLevelISA() instead. devEnableInterruptLevel() will
* be removed in a future release.
*/
epicsShareFunc long devEnableInterruptLevel(
epicsInterruptType intType, unsigned level);
/*
* NOTE: this routine has been deprecated. It exists
/**
* \note This routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devDisableInterruptLevelVME, devDisableInterruptLevelISA,
* devDisableInterruptLevelPCI etc. devDisableInterruptLevel will be removed
* in a future release.
* Please use one of devDisableInterruptLevelVME(), devDisableInterruptLevelISA(),
* devDisableInterruptLevelPCI() instead. devDisableInterruptLevel() will
* be removed in a future release.
*/
epicsShareFunc long devDisableInterruptLevel (
epicsInterruptType intType, unsigned level);
/*
* NOTE: this routine has been deprecated. It exists
/**
* \note This routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use devNoResponseProbe(). locationProbe() will be removed
* Please use devNoResponseProbe() instead. locationProbe() will be removed
* in a future release.
*/
epicsShareFunc long locationProbe (epicsAddressType addrType, char *pLocation);
/** @} */
#endif /* NO_DEVLIB_OLD_INTERFACE */
#ifdef __cplusplus

View File

@@ -6,14 +6,13 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLibImpl.h */
/*
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
/**
* \file devLibVMEImpl.h
* \author Marty Kraimer, Jeff Hill
* \brief An interface from devLibVME.c to its OS-specific implementations.
*/
#ifndef INCdevLibImplh
@@ -27,72 +26,57 @@
extern "C" {
#endif
/*
* virtual OS layer for devLib.c
/**
* \brief A table of function pointers for devLibVME implementations
*
* The global virtual OS table pdevLibVME controls
* The global virtual OS table \ref pdevLibVME controls
* the behaviour of the functions defined in devLib.h.
* All of which call into the functions found in this table
* to perform system specific tasks.
*/
typedef struct devLibVME {
/*
* maps logical address to physical address, but does not detect
* two device drivers that are using the same address range
*/
long (*pDevMapAddr) (epicsAddressType addrType, unsigned options,
size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
/** \brief Map a bus address to the CPU's address space. */
long (*pDevMapAddr) (epicsAddressType addrType, unsigned options,
size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
/*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
*/
long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr, void *pValueRead);
/** \brief Read a word, detect and protect against bus errors. */
long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr,
void *pValueRead);
/** \brief Write a word, detect and protect against bus errors. */
long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr,
const void *pValueWritten);
/*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr, const void *pValueWritten);
/** \brief Connect ISR to a VME interrupt vector. */
long (*pDevConnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *), void *parameter);
/** \brief Disconnect ISR from a VME interrupt vector. */
long (*pDevDisconnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *));
/*
* connect ISR to a VME interrupt vector
* (required for backwards compatibility)
*/
long (*pDevConnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *), void *parameter);
/** \brief Enable VME interrupt level to CPU. */
long (*pDevEnableInterruptLevelVME) (unsigned level);
/** \brief Disable VME interrupt level to CPU. */
long (*pDevDisableInterruptLevelVME) (unsigned level);
/*
* disconnect ISR from a VME interrupt vector
* (required for backwards compatibility)
*/
long (*pDevDisconnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *));
/** \brief Malloc a block accessible from the VME A24 address space. */
void *(*pDevA24Malloc)(size_t nbytes);
/** \brief Free a block allocated for the VME A24 address space. */
void (*pDevA24Free)(void *pBlock);
/*
* enable VME interrupt level
*/
long (*pDevEnableInterruptLevelVME) (unsigned level);
/** \brief Init devLib */
long (*pDevInit)(void);
/*
* disable VME interrupt level
*/
long (*pDevDisableInterruptLevelVME) (unsigned level);
/* malloc/free A24 address space */
void *(*pDevA24Malloc)(size_t nbytes);
void (*pDevA24Free)(void *pBlock);
long (*pDevInit)(void);
/*
* test if VME interrupt has an ISR connected
*/
int (*pDevInterruptInUseVME) (unsigned vectorNumber);
/** \brief Check if interrupt vector has an ISR connected. */
int (*pDevInterruptInUseVME)(unsigned vectorNumber);
}devLibVME;
/** \brief Pointer to the entry table used by devLibVME routines. */
epicsShareExtern devLibVME *pdevLibVME;
#ifndef NO_DEVLIB_COMPAT
/** \brief An alias for pdevLibVME */
# define pdevLibVirtualOS pdevLibVME
/** \brief A type definition for devLibVME */
typedef devLibVME devLibVirtualOS;
#endif

View File

@@ -4,14 +4,39 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* EPICS assert
/**\file epicsAssert.h
* \author Jeffery O. Hill
*
* Author: Jeffrey O. Hill
* Date: 022795
*/
* \brief An EPICS-specific replacement for ANSI C's assert.
*
* To use this version just include:
\code
#define epicsAssertAuthor "Code Author my@email.address"
#include <epicsAssert.h>
\endcode
* instead of
\code
#include <assert.h>
\endcode
*
* If an assert() fails, it calls errlog indicating the program's author, file name, and
* line number. Under each OS there are 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, and on posix there are
* instructions about saving the core file. After printing the message the calling thread
* is suspended. An author may, before the above include line, optionally define a
* preprocessor macro named epicsAssertAuthor as a string that provides their name and
* email address if they wish to be contacted when the assertion fires.
*
* This header also provides a compile-time assertion macro STATIC_ASSERT()
* which can be used to check a constant-expression at compile-time. The C or
* C++ compiler will flag an error if the expresstion evaluates to 0. The
* STATIC_ASSERT() macro can only be used where a \c typedef is syntactically
* legal.
**/
#ifndef INC_epicsAssert_H
#define INC_epicsAssert_H
@@ -25,6 +50,7 @@ extern "C" {
#ifndef epicsAssertAuthor
/**\brief Optional string giving the author's name */
# define epicsAssertAuthor 0
#endif
@@ -34,9 +60,13 @@ extern "C" {
# define assert(ignore) ((void) 0)
#else /* NDEBUG */
/**@private */
epicsShareFunc void epicsAssert (const char *pFile, const unsigned line,
const char *pExp, const char *pAuthorName);
/**\brief Declare that a condition should be true.
* \param exp Expression that should evaluate to True.
*/
# define assert(exp) ((exp) ? (void)0 : \
epicsAssert(__FILE__, __LINE__, #exp, epicsAssertAuthor))
@@ -49,6 +79,10 @@ epicsShareFunc void epicsAssert (const char *pFile, const unsigned line,
#else
#define STATIC_JOIN(x, y) STATIC_JOIN2(x, y)
#define STATIC_JOIN2(x, y) x ## y
/**\brief Declare a condition that should be true at compile-time.
* \param expr A C/C++ const-expression that should evaluate to True.
*/
#define STATIC_ASSERT(expr) \
typedef int STATIC_JOIN(static_assert_failed_at_line_, __LINE__) \
[ (expr) ? 1 : -1 ] EPICS_UNUSED

View File

@@ -4,26 +4,62 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**\file epicsEvent.h
*
* \brief APIs for the epicsEvent binary semaphore.
*
* Defines the C++ and C API's 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.
*
* 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.
\code
epicsEvent *pevent = new epicsEvent;
\endcode
* The consumer thread has code containing:
\code
while(1) {
pevent->wait();
while( {more work} ) {
{process work}
}
}
\endcode
* Producers create requests and issue the statement:
\code
pevent->trigger();
\endcode
**/
#ifndef epicsEventh
#define epicsEventh
#include "shareLib.h"
/** \brief An identifier for an epicsEvent for use with the C API */
typedef struct epicsEventOSD *epicsEventId;
/** \brief Return status from several C API routines. */
typedef enum {
epicsEventOK = 0,
epicsEventWaitTimeout,
epicsEventError
} epicsEventStatus;
/* Backwards compatibility */
/** \brief Old name provided for backwards compatibility */
#define epicsEventWaitStatus epicsEventStatus
/** \brief Old name provided for backwards compatibility */
#define epicsEventWaitOK epicsEventOK
/** \brief Old name provided for backwards compatibility */
#define epicsEventWaitError epicsEventError
/** \brief Possible initial states of a new epicsEvent */
typedef enum {
epicsEventEmpty,
epicsEventFull
@@ -31,15 +67,50 @@ typedef enum {
#ifdef __cplusplus
/**\brief A binary semaphore.
*
* An epicsEvent is a binary semaphore that can be empty or full.
* When empty, a wait() issued before the next call to trigger() will block.
* When full, the next call to wait() will empty the event and return
* immediately. Multiple calls to trigger() may occur between wait() calls
* but will have the same effect as a single trigger(), filling the event.
**/
class epicsShareClass epicsEvent {
public:
/**\brief Constructor.
* \param initial State when created, empty (the default) or full.
**/
epicsEvent ( epicsEventInitialState initial = epicsEventEmpty );
/**\brief Destroy the epicsEvent and any resources it holds. No calls to
* wait() can be active when this call is made.
**/
~epicsEvent ();
/**\brief Trigger the event i.e. ensures the next or current call to wait
* completes. This method may be called from a vxWorks or RTEMS interrupt
* handler.
**/
void trigger ();
/**\brief Signal is a synonym for 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 */
/**\brief Wait for the event.
* \note Blocks until full.
**/
void wait ();
/**\brief Wait for the event or until the specified timeout.
* \param timeOut The timeout delay in seconds.
* \return True if the event was triggered, False if it timed out.
**/
bool wait ( double timeOut );
/**\brief Similar to wait() except that if the event is currenly empty the
* call will return immediately.
* \return True if the event was full (triggered), False if empty.
**/
bool tryWait ();
/**\brief Display information about the semaphore.
* \note The information displayed is architecture dependant.
* \param level An unsigned int for the level of information to be displayed.
**/
void show ( unsigned level ) const;
class invalidSemaphore; /* exception payload */
@@ -52,22 +123,91 @@ private:
extern "C" {
#endif /*__cplusplus */
/**\brief Create an epicsEvent for use from C code, or return NULL.
*
* \param initialState Starting state, \c epicsEventEmpty or \c epicsEventFull.
* \return An identifier for the new event, or NULL if one not be created.
**/
epicsShareFunc epicsEventId epicsEventCreate(
epicsEventInitialState initialState);
/**\brief Create an epicsEvent for use from C code.
*
* This routine does not return if the object could not be created.
* \param initialState Starting state, \c epicsEventEmpty or \c epicsEventFull.
* \return An identifier for the new event.
**/
epicsShareFunc epicsEventId epicsEventMustCreate (
epicsEventInitialState initialState);
/**\brief Destroy an epicsEvent and any resources it holds.
*
* No calls to any epicsEventWait routines can be active when this call is made.
* \param id The event identifier.
**/
epicsShareFunc void epicsEventDestroy(epicsEventId id);
/**\brief Trigger an event i.e. ensures the next or current call to wait
* completes.
*
* \note This method may be called from a VxWorks or RTEMS interrupt
* handler.
* \param id The event identifier.
* \return Status indicator.
**/
epicsShareFunc epicsEventStatus epicsEventTrigger(
epicsEventId id);
/**\brief Trigger an event.
*
* This routine does not return if the identifier is invalid.
* \param id The event identifier.
*/
epicsShareFunc void epicsEventMustTrigger(epicsEventId id);
/**\brief A synonym for epicsEventTrigger().
* \param ID The event identifier.
* \return Status indicator.
**/
#define epicsEventSignal(ID) epicsEventMustTrigger(ID)
/**\brief Wait for an event.
* \note Blocks until full.
* \param id The event identifier.
* \return Status indicator.
**/
epicsShareFunc epicsEventStatus epicsEventWait(
epicsEventId id);
/**\brief Wait for an event (see epicsEventWait()).
*
* This routine does not return if the identifier is invalid.
* \param id The event identifier.
*/
epicsShareFunc void epicsEventMustWait(epicsEventId id);
/**\brief Wait an the event or until the specified timeout period is over.
* \note Blocks until full or timeout.
* \param id The event identifier.
* \param timeOut The timeout delay in seconds.
* \return Status indicator.
**/
epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout(
epicsEventId id, double timeOut);
/**\brief Similar to wait() except that if the event is currenly empty the
* call will return immediately with status \c epicsEventWaitTimeout.
* \param id The event identifier.
* \return Status indicator, \c epicsEventWaitTimeout when the event is empty.
**/
epicsShareFunc epicsEventStatus epicsEventTryWait(
epicsEventId id);
/**\brief Display information about the semaphore.
* \note The information displayed is architecture dependant.
* \param id The event identifier.
* \param level An unsigned int for the level of information to be displayed.
**/
epicsShareFunc void epicsEventShow(
epicsEventId id, unsigned int level);

View File

@@ -7,6 +7,32 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**\file epicsGeneralTime.h
*
* \brief The generalTime framework provides a mechanism for several time providers to be
* present within the system.
*
* There are two types of time provider, one type provides the current wall-clock
* time, the other provides Event System times. Each time provider is registered with
* 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 highest 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 that will be called from
* the epicsTimeGetCurrentInt() or epicsTimeGetEventInt() API routines. These interfaces
* cannot check the priority queue, so will only succeed if the last-used provider has
* registered a suitable routine.
*
* \note There are two interfaces to this framework, epicsGeneralTime.h for consumers
* to obtain a time and query the framework, and generalTimeSup.h for providers
* that can supply timestamps.
**/
#ifndef INC_epicsGeneralTime_H
#define INC_epicsGeneralTime_H
@@ -16,28 +42,109 @@
extern "C" {
#endif
/**\def NUM_TIME_EVENTS
* \brief The number of time events that are validated.
*
* Time Events numbered 0 through (NUM_TIME_EVENTS-1) are validated by code in
* epicsGeneralTime.c that tests for advancing timestamps and enforces that
* restriction.
*
* \note Event numbers greater than or equal to NUM_TIME_EVENTS are now allowed
* if supported by a custom time provider which should provide its own advancing
* timestamp validation.
**/
#define NUM_TIME_EVENTS 256
/* Time Events numbered 0 through (NUM_TIME_EVENTS-1) are validated by */
/* code in epicsGeneralTime.c that tests for advancing timestamps and */
/* enforces that restriction. Event numbers greater than or equal to */
/* NUM_TIME_EVENTS are now allowed if supported by a custom time provider */
/* which should provide its own advancing timestamp validation. */
/**\brief Initialise the framework.
*
* This routine is called automatically by any function that requires the
* framework. It does not need to be called explicitly.
**/
epicsShareFunc void generalTime_Init(void);
/**\brief Install a Time Event time provider that returns the current time for any
* Time event number.
*
* \note 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.
**/
epicsShareFunc int installLastResortEventProvider(void);
/**\brief Reset the internal counter of the number of times the time returned was
* earlier than when previously requested.
*
* Used by device support for binary out record
* with:
\code
DTYP = "General Time"
OUT = "@RSTERRCNT"
\endcode
**/
epicsShareFunc void generalTimeResetErrorCounts(void);
/**\brief 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:
\code
DTYP = "General Time"
INP = "@GETERRCNT"
\endcode
*
* \return Reset error counts
**/
epicsShareFunc int generalTimeGetErrorCounts(void);
/**\brief Return the nume of the provider that last returned a valid current time, or
* NULL if none.
*
* Used by stringin device support with:
\code
DTYP = "General Time"
INP = "@BESTTCP"
\endcode
*
* \return Provider name
**/
epicsShareFunc const char * generalTimeCurrentProviderName(void);
/**\brief Return the name of the provider that last returned a valid Time Event time, or
* NULL of none.
*
* Used by stringin device support with:
\code
DTYP = "General Time"
INP = "@BESTTEP"
\endcode
*
* \return Provider name
**/
epicsShareFunc const char * generalTimeEventProviderName(void);
/**\brief Return the name of the registered current time provider that has the highest
* priority.
*
* Used by stringin device support with:
\code
DTYP = "General Time"
INP = "@TOPTCP"
\endcode
*
* \return Provider name
**/
epicsShareFunc const char * generalTimeHighestCurrentName(void);
/* Original names, for compatibility */
/** \brief Old name provided for backwards compatibility */
#define generalTimeCurrentTpName generalTimeCurrentProviderName
/** \brief Old name provided for backwards compatibility */
#define generalTimeEventTpName generalTimeEventProviderName
/**\brief Provide information about the installed providers and their current best times.
*
* \param interest Desired interest level to report
**/
epicsShareFunc long generalTimeReport(int interest);
#ifdef __cplusplus

View File

@@ -5,17 +5,18 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author W. Eric Norum
* norume@aps.anl.gov
* 630 252 4793
/**
* \file epicsMessageQueue.h
* \author W. Eric Norum
*
* \brief A C++ and a C facility for communication between threads.
*
* Each C function corresponds to one of the C++ methods.
*/
/*
* Interthread message passing
*/
#ifndef epicsMessageQueueh
#define epicsMessageQueueh
@@ -26,22 +27,135 @@ typedef struct epicsMessageQueueOSD *epicsMessageQueueId;
#ifdef __cplusplus
/** 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.
*
* A C++ epicsMessageQueue cannot be assigned to, copy-constructed, or
* constructed without giving the capacity and max-imumMessageSize
* arguments.
*
* The C++ compiler will object to some of the statements below:
* \code{.cpp}
* 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
* \endcode
**/
class epicsShareClass epicsMessageQueue {
public:
/**
* \brief Constructor.
* \param capacity Maximum number of messages to queue
* \param maximumMessageSize Number of bytes of the largest
* message that may be queued
**/
epicsMessageQueue ( unsigned int capacity,
unsigned int maximumMessageSize );
/**
* \brief Destructor.
**/
~epicsMessageQueue ();
/**
* \brief Try to send a message.
* \note On VxWorks and RTEMS this method may be called from
* an interrupt handler.
* \returns 0 if the message was sent to a receiver or queued for
* future delivery.
* \returns -1 if no more messages can be queued or if the message
* is larger than the queue's maximum message size.
**/
int trySend ( void *message, unsigned int messageSize );
int send ( void *message, unsigned int messageSize);
/**
* \brief Send a message.
* \returns 0 if the message was sent to a receiver or queued for
* future delivery.
* \returns -1 if the message is larger than the queue's maximum
* message size.
**/
int send ( void *message, unsigned int messageSize );
/**
* \brief Send a message or timeout.
* \returns 0 if the message was sent to a receiver or queued for
* future delivery.
* \returns -1 if the timeout was reached before the
* message could be sent or queued, or if the message is larger
* than the queue's maximum message size.
**/
int send ( void *message, unsigned int messageSize, double timeout );
/**
* \brief Try to receive a message.
* If the queue holds at least one message,
* the first message on the queue is moved to the specified location
* and the length of that message is returned.
*
* If the received message is larger than the specified message size
* the implementation 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.
* \returns Number of bytes in the message.
* \returns -1 if the message queue is empty, or the buffer too small.
**/
int tryReceive ( void *message, unsigned int size );
/**
* \brief Fetch the next message on the queue.
* Wait for a message to be sent if the queue is empty, then move
* the first message queued to the specified location.
*
* If the received message is larger than the specified message size
* the implementation 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.
* \returns Number of bytes in the message.
* \returns -1 if the buffer is too small for the message.
**/
int receive ( void *message, unsigned int size );
/**
* \brief Wait for a message to be queued.
* Wait up to \p timeout seconds for a message to be sent if the queue
* is empty, then move the first message to the specified location.
*
* 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.
* \returns Number of bytes in the message.
* \returns -1 if a message is not received within the timeout
* interval.
**/
int receive ( void *message, unsigned int size, double timeout );
/**
* \brief Displays some information about the message queue.
* \param level Controls the amount of information displayed.
**/
void show ( unsigned int level = 0 );
/**
* \brief How many messages are queued.
* \returns The number of messages presently in the queue.
**/
unsigned int pending ();
private: /* Prevent compiler-generated member functions */
/* default constructor, copy constructor, assignment operator */
private:
/**
* Prevent compiler-generated member functions default constructor,
* copy constructor, assignment operator.
**/
epicsMessageQueue();
epicsMessageQueue(const epicsMessageQueue &);
epicsMessageQueue& operator=(const epicsMessageQueue &);
@@ -52,39 +166,136 @@ private: /* Prevent compiler-generated member functions */
extern "C" {
#endif /*__cplusplus */
/**
* \brief Create a message queue.
* \param capacity Maximum number of messages to queue
* \param maximumMessageSize Number of bytes of the largest
* message that may be queued
* \return An identifier for the new queue, or 0.
**/
epicsShareFunc epicsMessageQueueId epicsShareAPI epicsMessageQueueCreate(
unsigned int capacity,
unsigned int maximumMessageSize);
/**
* \brief Destroy a message queue, release all its memory.
**/
epicsShareFunc void epicsShareAPI epicsMessageQueueDestroy(
epicsMessageQueueId id);
/**
* \brief Try to send a message.
* \note On VxWorks and RTEMS this routine may be called from
* an interrupt handler.
* \returns 0 if the message was sent to a receiver or queued for
* future delivery.
* \returns -1 if no more messages can be queued or if the message
* is larger than the queue's maximum message size.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueueTrySend(
epicsMessageQueueId id,
void *message,
unsigned int messageSize);
/**
* \brief Send a message.
* \returns 0 if the message was sent to a receiver or queued for
* future delivery.
* \returns -1 if the message is larger than the queue's maximum
* message size.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueueSend(
epicsMessageQueueId id,
void *message,
unsigned int messageSize);
/**
* \brief Send a message or timeout.
* \returns 0 if the message was sent to a receiver or queued for
* future delivery.
* \returns -1 if the timeout was reached before the
* message could be sent or queued, or if the message is larger
* than the queue's maximum message size.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueueSendWithTimeout(
epicsMessageQueueId id,
void *message,
unsigned int messageSize,
double timeout);
/**
* \brief Try to receive a message.
*
* If the queue holds at least one message,
* the first message on the queue is moved to the specified location
* and the length of that message is returned.
*
* If the received message is larger than the specified message size
* the implementation 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.
* \returns Number of bytes in the message.
* \returns -1 if the message queue is empty, or the buffer too small.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueueTryReceive(
epicsMessageQueueId id,
void *message,
unsigned int size);
/**
* \brief Fetch the next message on the queue.
*
* Wait for a message to be sent if the queue is empty, then move the
* first message queued to the specified location.
*
* If the received message is larger than the specified message size
* the implementation 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.
* \returns Number of bytes in the message.
* \returns -1 if the buffer is too small for the message.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueueReceive(
epicsMessageQueueId id,
void *message,
unsigned int size);
/**
* \brief Wait for a message to be queued.
*
* Wait up to \p timeout seconds for a message to be sent if the queue
* is empty, then move the first message to the specified location.
*
* If the received message is larger than the specified message buffer
* size the implementation 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.
* \returns Number of bytes in the message.
* \returns -1 if a message is not received within the timeout
* interval.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueueReceiveWithTimeout(
epicsMessageQueueId id,
void *message,
unsigned int size,
double timeout);
/**
* \brief How many messages are queued.
* \param id Message queue identifier.
* \returns The number of messages presently in the queue.
**/
epicsShareFunc int epicsShareAPI epicsMessageQueuePending(
epicsMessageQueueId id);
/**
* \brief Displays some information about the message queue.
* \param id Message queue identifier.
* \param level Controls the amount of information displayed.
**/
epicsShareFunc void epicsShareAPI epicsMessageQueueShow(
epicsMessageQueueId id,
int level);

View File

@@ -3,10 +3,34 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**\file epicsMutex.h
*
* \brief APIs for the epicsMutex mutual exclusion semaphore
*
* Mutual exclusion semaphores are for situations requiring exclusive access to
* resources. An epicsMutex may be claimed recursively, i.e. taken more than
* once by a thread, which must release it as many times as it was taken.
* Recursive usage is common for a set of routines that call each other while
* working on an exclusive resource.
*
* The typical C++ use of a mutual exclusion semaphore is:
\code
epicsMutex *plock = new epicsMutex;
...
...
plock->lock();
// process resources
plock->unlock();
\endcode
*
* \note The implementation:
* - MUST implement recursive locking
* - SHOULD implement priority inheritance and deletion safety if possible.
**/
#ifndef epicsMutexh
#define epicsMutexh
@@ -14,9 +38,14 @@
#include "shareLib.h"
/**\brief An identifier for an epicsMutex for use with the C API */
typedef struct epicsMutexParm *epicsMutexId;
/** Return status from some C API routines. */
typedef enum {
epicsMutexLockOK,epicsMutexLockTimeout,epicsMutexLockError
epicsMutexLockOK = 0,
epicsMutexLockTimeout,
epicsMutexLockError
} epicsMutexLockStatus;
#ifdef __cplusplus
@@ -24,31 +53,82 @@ typedef enum {
#include "compilerDependencies.h"
#include "epicsGuard.h"
/**\brief Create a C++ epicsMutex with current filename and line number
*/
#define newEpicsMutex new epicsMutex(__FILE__,__LINE__)
/**\brief The C++ API for an epicsMutex.
*/
class epicsShareClass epicsMutex {
public:
typedef epicsGuard<epicsMutex> guard_t;
typedef epicsGuard<epicsMutex> release_t;
class mutexCreateFailed; /* exception payload */
class invalidMutex; /* exception payload */
#if !defined(__GNUC__) || __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<8)
/**\brief Create a mutual exclusion semaphore.
**/
epicsMutex ();
/**\brief Create a mutual exclusion semaphore with source location.
*
* \note The newEpicsMutex macro simplifies using this constructor.
* \param *pFileName Source file name.
* \param lineno Source line number
**/
epicsMutex ( const char *pFileName, int lineno );
#else
/**\brief Create a mutual exclusion semaphore.
* \param *pFileName Source file name.
* \param lineno Source line number
**/
epicsMutex ( const char *pFileName = __builtin_FILE(), int lineno = __builtin_LINE() );
#endif
/**\brief Delete the semaphore and its resources.
**/
~epicsMutex ();
/**\brief Display information about the semaphore.
*
* \note Results are architecture dependant.
*
* \param level Desired information level to report
**/
void show ( unsigned level ) const;
void lock (); /* blocks until success */
/**\brief Claim the semaphore, waiting until it's free if currently owned
* owned by a different thread.
*
* This call blocks until the calling thread can get exclusive access to
* the semaphore.
* \note After a successful lock(), additional recursive locks may be
* issued by the same thread, but each must have an associated unlock().
**/
void lock ();
/**\brief Release the semaphore.
*
* \note If a thread issues recursive locks, it must call unlock() as many
* times as it calls lock().
**/
void unlock ();
bool tryLock (); /* true if successful */
/**\brief Similar to lock() except that the call returns immediately if the
* semaphore is currently owned by another thread, giving the value false.
*
* \return True if the resource is now owned by the caller.
* \return False if some other thread already owns the resource.
**/
bool tryLock ();
private:
epicsMutexId id;
epicsMutex ( const epicsMutex & );
epicsMutex & operator = ( const epicsMutex & );
};
/**\brief A semaphore for locating deadlocks in C++ code. */
class epicsShareClass epicsDeadlockDetectMutex {
public:
typedef epicsGuard<epicsDeadlockDetectMutex> guard_t;
@@ -74,36 +154,96 @@ private:
extern "C" {
#endif /*__cplusplus*/
/**\brief Create an epicsMutex semaphore for use from C code.
*
* This macro stores the source location of the creation call in the mutex.
* \return An identifier for the mutex, or NULL if one could not be created.
**/
#define epicsMutexCreate() epicsMutexOsiCreate(__FILE__,__LINE__)
/**\brief Internal API, used by epicsMutexCreate(). */
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiCreate(
const char *pFileName,int lineno);
/**\brief Create an epicsMutex semaphore for use from C code.
*
* This macro stores the source location of the creation call in the mutex.
* The routine does not return if the object could not be created.
* \return An identifier for the mutex.
**/
#define epicsMutexMustCreate() epicsMutexOsiMustCreate(__FILE__,__LINE__)
/**\brief Internal API, used by epicsMutexMustCreate(). */
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiMustCreate(
const char *pFileName,int lineno);
/**\brief Destroy an epicsMutex semaphore.
* \param id The mutex identifier.
**/
epicsShareFunc void epicsShareAPI epicsMutexDestroy(epicsMutexId id);
/**\brief Release the semaphore.
* \param id The mutex identifier.
* \note If a thread issues recursive locks, it must call epicsMutexUnlock()
* as many times as it calls epicsMutexLock() or equivalents.
**/
epicsShareFunc void epicsShareAPI epicsMutexUnlock(epicsMutexId id);
/**\brief Claim the semaphore, waiting until it's free if currently owned
* owned by a different thread.
*
* This call blocks until the calling thread can get exclusive access to
* the semaphore.
* \note After a successful lock(), additional recursive locks may be
* issued by the same thread, but each must have an associated unlock().
* \param id The mutex identifier.
* \return Status indicator.
**/
epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLock(
epicsMutexId id);
/**\brief Claim a semaphore (see epicsMutexLock()).
*
* This routine does not return if the identifier is invalid.
* \param ID The mutex identifier.
**/
#define epicsMutexMustLock(ID) { \
epicsMutexLockStatus status = epicsMutexLock(ID); \
assert(status == epicsMutexLockOK); \
}
/**\brief Similar to epicsMutexLock() except that the call returns immediately,
* with the return status indicating if the semaphore is currently owned by
* this thread or another thread.
*
* \return \c epicsMutexLockOK if the resource is now owned by the caller.
* \return \c epicsMutexLockTimeout if some other thread owns the resource.
**/
epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexTryLock(
epicsMutexId id);
/**\brief Display information about the semaphore.
*
* \note Results are architecture dependant.
*
* \param id The mutex identifier.
* \param level Desired information level to report
**/
epicsShareFunc void epicsShareAPI epicsMutexShow(
epicsMutexId id,unsigned int level);
/**\brief Display information about all epicsMutex semaphores.
*
* \note Results are architecture dependant.
*
* \param onlyLocked Non-zero to show only locked semaphores.
* \param level Desired information level to report
**/
epicsShareFunc void epicsShareAPI epicsMutexShowAll(
int onlyLocked,unsigned int level);
/*NOTES:
epicsMutex MUST implement recursive locking
epicsMutex should implement priority inheritance and deletion safe
*/
/*
* The following is the interface to the OS dependent
* implementation and should NOT be called directly by
* user code
/**@privatesection
* The following are interfaces to the OS dependent
* implementation and should NOT be called directly by
* user code.
*/
struct epicsMutexOSD * epicsMutexOsdCreate(void);
void epicsMutexOsdDestroy(struct epicsMutexOSD *);

View File

@@ -6,6 +6,16 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**
* \file epicsReadline.h
* \brief Command-line editing functions
* \author Eric Norum
*
* Provides a generalized API for command line history and line-editing.
* The implementation of this API can call GNU Readline, libtecla, and on
* VxWorks the ledLib routines, according to the EPICS build configuration.
*/
#ifndef INC_epicsReadline_H
#define INC_epicsReadline_H
@@ -15,9 +25,23 @@ extern "C" {
#include <shareLib.h>
#include <stdio.h>
/**
* \brief Create a command-line context
* \param in Filehandle to read from
* \return Command-line context
*/
epicsShareFunc void * epicsShareAPI epicsReadlineBegin (FILE *in);
/**
* \brief Read a line of input
* \param prompt Prompt string
* \param context To read from
* \return Line read
*/
epicsShareFunc char * epicsShareAPI epicsReadline (const char *prompt, void *context);
/**
* \brief Destroy a command-line context
* \param context Command-line context to destroy
*/
epicsShareFunc void epicsShareAPI epicsReadlineEnd (void *context);
#ifdef __cplusplus

View File

@@ -16,30 +16,33 @@ extern "C" {
#include "shareLib.h"
/*
/** \file epicsSignal.h
* \brief OS-independent routines for ignoring Posix signals
*
* The requests in this interface are typically ignored on OS that do not implement
* POSIX signals.
*/
struct epicsThreadOSD;
/*
/** Ignore the SIGHUP signal.
* Required to avoid problems with soft IOCs getting SIGHUPs when a
* Channel Access client disconnects
*/
epicsShareFunc void epicsShareAPI epicsSignalInstallSigHupIgnore ( void );
/*
/** Ignore the SIGPIPE signal.
* Required to avoid terminating a process which is blocking in a
* socket send() call when the SIGPIPE signal is generated by the OS.
*/
epicsShareFunc void epicsShareAPI epicsSignalInstallSigPipeIgnore ( void );
/*
* required only if shutdown() and close() do not interrupt a thread blocking in
/** Ignore the SIGALRM signal.
* Required only if shutdown() and close() do not interrupt a thread blocking in
* a socket system call
*/
epicsShareFunc void epicsShareAPI epicsSignalInstallSigAlarmIgnore ( void );
/** Raise a SIGALRM signal to a specific epicsThread */
epicsShareFunc void epicsShareAPI epicsSignalRaiseSigAlarm ( struct epicsThreadOSD * );
#ifdef __cplusplus

View File

@@ -4,10 +4,13 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* epicsTempFile.h */
/**
* \file epicsTempFile.h
* \brief OS-independent way to create temporary files.
**/
#ifndef INC_epicsTempFile_H
#define INC_epicsTempFile_H
@@ -20,6 +23,10 @@
extern "C" {
#endif
/**
* \brief Create and open a temporary file.
* \return NULL or a FILE pointer to a temporary file.
**/
epicsShareFunc FILE * epicsShareAPI epicsTempFile(void);
#ifdef __cplusplus

View File

@@ -5,8 +5,53 @@
* Operator of Los Alamos National Laboratory.
* Copyright (c) 2013 ITER Organization.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**
* \file epicsThread.h
*
* \brief C++ and C descriptions for a thread.
*
* The epicsThread API is meant as a somewhat minimal interface for
* multithreaded applications. It can be implementedon a wide variety of
* systems with the restriction that the system MUST support a
* multithreaded environment.
* A POSIX pthreads version is provided.
*
* The interface provides the following thread facilities,
* with restrictions as noted:
* - Life cycle: a thread starts life as a result of a call to
* epicsThreadCreate. It terminates when the thread function returns.
* It should not return until it has released all resources it uses.
* If a thread is expected to terminate as a natural part of its life
* cycle then the thread function must return.
* - epicsThreadOnce: this provides the ability to have an
* initialization function that is guaranteed to be called exactly
* once.
* - main: if a main routine finishes its work but wants to leave other
* threads running it can call epicsThreadExitMain, which should be
* the last statement in main.
* - Priorities: ranges between 0 and 99 with a higher number meaning
* higher priority. A number of constants are defined for iocCore
* specific threads. The underlying implementation may collapse the
* range 0 to 99 into a smaller range; even a single priority. User
* code should never rely on the existence of multiple thread
* priorities to guarantee correct behavior.
* - Stack Size: epicsThreadCreate accepts a stack size parameter. Three
* generic sizes are available: small, medium,and large. Portable code
* should always use one of the generic sizes. Some implementation may
* ignore the stack size request and use a system default instead.
* Virtual memory systems providing generous stack sizes can be
* expected to use the system default.
* - epicsThreadId: every epicsThread has an Id which gets returned by
* epicsThreadCreate and is valid as long as that thread still exists.
* A value of 0 always means no thread. If a threadId is used after
* the thread has terminated,the results are not defined (but will
* normally lead to bad things happening). Thus code that looks after
* other threads MUST be aware of threads terminating.
*/
#ifndef epicsThreadh
#define epicsThreadh
@@ -20,6 +65,9 @@ extern "C" {
typedef void (*EPICSTHREADFUNC)(void *parm);
/** @name Some Named Thread Priorities
* @{
*/
#define epicsThreadPriorityMax 99
#define epicsThreadPriorityMin 0
@@ -35,8 +83,9 @@ typedef void (*EPICSTHREADFUNC)(void *parm);
#define epicsThreadPriorityScanHigh 70
#define epicsThreadPriorityIocsh 91
#define epicsThreadPriorityBaseMax 91
/** @} */
/* stack sizes for each stackSizeClass are implementation and CPU dependent */
/** Stack sizes for each stackSizeClass are implementation and CPU dependent. */
typedef enum {
epicsThreadStackSmall, epicsThreadStackMedium, epicsThreadStackBig
} epicsThreadStackSizeClass;
@@ -45,11 +94,15 @@ typedef enum {
epicsThreadBooleanStatusFail, epicsThreadBooleanStatusSuccess
} epicsThreadBooleanStatus;
/** Lookup target specific default stack size */
/**
* Get a stack size value that can be given to epicsThreadCreate().
* \param size one of the values epicsThreadStackSmall,
* epicsThreadStackMedium or epicsThreadStackBig.
**/
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize(
epicsThreadStackSizeClass size);
/* (epicsThreadId)0 is guaranteed to be an invalid thread id */
/** (epicsThreadId)0 is guaranteed to be an invalid thread id */
typedef struct epicsThreadOSD *epicsThreadId;
typedef epicsThreadId epicsThreadOnceId;
@@ -57,27 +110,38 @@ typedef epicsThreadId epicsThreadOnceId;
/** Perform one-time initialization.
*
* Run the provided function if it has not run, and is not running.
* Run the provided function if it has not run, and is not running in
* some other thread.
*
* @post The provided function has been run.
* For each unique epicsThreadOnceId, epicsThreadOnce guarantees that
* -# myInitFunc will only be called only once.
* -# myInitFunc will have returned before any other epicsThreadOnce
* call using the same epicsThreadOnceId returns.
*
* @code
* \code
* static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
* static void myInitFunc(void *arg) { ... }
* static void some Function(void) {
* epicsThreadOnce(&onceId, &myInitFunc, NULL);
* }
* @endcode
* \endcode
*/
epicsShareFunc void epicsShareAPI epicsThreadOnce(
epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg);
/* When real-time scheduling is active, attempt any post-init operations
/**
* 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.
*/
**/
epicsShareFunc void epicsThreadRealtimeLock(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.
**/
epicsShareFunc void epicsShareAPI epicsThreadExitMain(void);
/** For use with epicsThreadCreateOpt() */
@@ -103,12 +167,12 @@ typedef struct epicsThreadOpts {
#define EPICS_THREAD_OPTS_INIT { \
epicsThreadPriorityLow, epicsThreadStackMedium, 0}
/** @brief Allocate and start a new OS thread.
* @param name A name describing this thread. Appears in various log and error message.
* @param funptr The thread main function.
* @param parm Passed to thread main function.
* @param opts Modifiers for the new thread, or NULL to use target specific defaults.
* @return NULL on error
/** \brief Allocate and start a new OS thread.
* \param name A name describing this thread. Appears in various log and error message.
* \param funptr The thread main function.
* \param parm Passed to thread main function.
* \param opts Modifiers for the new thread, or NULL to use target specific defaults.
* \return NULL on error
*/
epicsShareFunc epicsThreadId epicsThreadCreateOpt (
const char * name,
@@ -156,16 +220,20 @@ epicsShareFunc epicsThreadBooleanStatus epicsShareAPI
/** Test if two thread IDs actually refer to the same OS thread */
epicsShareFunc int epicsShareAPI epicsThreadIsEqual(
epicsThreadId id1, epicsThreadId id2);
/** Test if thread has been suspended with epicsThreadSuspendSelf() */
/** 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.
**/
epicsShareFunc int epicsShareAPI epicsThreadIsSuspended(epicsThreadId id);
/** @brief Block the calling thread for at least the specified time.
* @param seconds Time to wait in seconds. Values <=0 blocks for the shortest possible time.
/** \brief Block the calling thread for at least the specified time.
* \param seconds Time to wait in seconds. Values <=0 blocks for the shortest possible time.
*/
epicsShareFunc void epicsShareAPI epicsThreadSleep(double seconds);
/** @brief Query a value approximating the OS timer/scheduler resolution.
* @return A value in seconds >=0
/** \brief Query a value approximating the OS timer/scheduler resolution.
* \return A value in seconds >=0
*
* @warning On targets other than vxWorks and RTEMS, the quantum value often isn't
* \warning On targets other than vxWorks and RTEMS, the quantum value often isn't
* meaningful. Use of this function is discouraged in portable code.
*/
epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum(void);
@@ -174,23 +242,23 @@ epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum(void);
*/
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf(void);
/** Attempt to find the first instance of a thread by name.
* @return An epicsThreadId, or NULL if no such thread is currently running.
* \return 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
* \warning Safe use of this function requires external knowledge that this
* thread will not return.
*/
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetId(const char *name);
/** Return a value approximating the number of threads which this target
* can run in parallel. This value is advisory.
* @return >=1
* \return >=1
*/
epicsShareFunc int epicsThreadGetCPUs(void);
/** Return the name of the current thread.
*
* @return Never NULL. Storage lifetime tied to epicsThreadId.
* \return 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.
@@ -206,22 +274,54 @@ epicsShareFunc const char * epicsShareAPI epicsThreadGetNameSelf(void);
epicsShareFunc void epicsShareAPI epicsThreadGetName(
epicsThreadId id, char *name, size_t size);
/**
* 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.
**/
epicsShareFunc int epicsShareAPI epicsThreadIsOkToBlock(void);
/**
* 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.
**/
epicsShareFunc void epicsShareAPI epicsThreadSetOkToBlock(int isOkToBlock);
/** Print to stdout information about all running EPICS threads.
* @param level 0 prints minimal output. Higher values print more details.
* \param level 0 prints minimal output. Higher values print more details.
*/
epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level);
/** Print info about a single EPICS thread. */
epicsShareFunc void epicsShareAPI epicsThreadShow(
epicsThreadId id,unsigned int level);
/* Hooks called when a thread starts, map function called once for every thread */
/**
* Hooks called when a thread starts, map function called once for every thread.
**/
typedef void (*EPICS_THREAD_HOOK_ROUTINE)(epicsThreadId id);
/**
* 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.
*/
epicsShareFunc int epicsThreadHookAdd(EPICS_THREAD_HOOK_ROUTINE hook);
/**
* Remove routine from the list of hooks run at thread creation time.
**/
epicsShareFunc int epicsThreadHookDelete(EPICS_THREAD_HOOK_ROUTINE hook);
/**
* Print the current list of hook function pointers.
**/
epicsShareFunc void epicsThreadHooksShow(void);
/**
* Call func once for every known thread.
**/
epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func);
/** Thread local storage */
@@ -260,18 +360,18 @@ public:
extern "C" void epicsThreadCallEntryPoint ( void * );
/** @brief An OS thread
/** \brief An OS thread
*
* A wrapper around the epicsThread* C API.
*
* @note Threads must be start() ed.
* \note Threads must be start() ed.
*/
class epicsShareClass epicsThread {
public:
/** Create a new thread with the provided information.
*
* cf. epicsThreadOpts
* @note Threads must be start() ed.
* \note Threads must be start() ed.
* @throws epicsThread::unableToCreateThread on error.
*/
epicsThread ( epicsThreadRunable &,const char *name, unsigned int stackSize,
@@ -282,11 +382,11 @@ public:
//! Wait for the thread epicsRunnable::run() to return.
void exitWait () throw ();
//! Wait for the thread epicsRunnable::run() to return.
//! @param delay Wait up to this many seconds.
//! @returns true if run() returned. false on timeout.
//! \param delay Wait up to this many seconds.
//! \return true if run() returned. false on timeout.
bool exitWait ( const double delay ) throw ();
//! @throws A special exitException which will be caught and ignored.
//! @note This exitException doesn't not derive from std::exception
//! \note This exitException doesn't not derive from std::exception
static void exit ();
//! cf. epicsThreadResume()
void resume () throw ();
@@ -300,7 +400,7 @@ public:
void setPriority ( unsigned int ) throw ();
bool priorityIsEqual ( const epicsThread & ) const throw ();
bool isSuspended () const throw ();
//! @return true if call through this thread's epicsRunnable::run()
//! \return true if call through this thread's epicsRunnable::run()
bool isCurrentThread () const throw ();
bool operator == ( const epicsThread & ) const throw ();
//! Say something interesting about this thread to stdout.
@@ -331,7 +431,7 @@ private:
epicsThread ( const epicsThread & );
epicsThread & operator = ( const epicsThread & );
friend void epicsThreadCallEntryPoint ( void * );
void printLastChanceExceptionMessage (
void printLastChanceExceptionMessage (
const char * pExceptionTypeName,
const char * pExceptionContext );
/* exceptions */
@@ -346,7 +446,7 @@ protected:
};
template < class T >
class epicsThreadPrivate :
class epicsThreadPrivate :
private epicsThreadPrivateBase {
public:
epicsThreadPrivate ();

View File

@@ -4,10 +4,13 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* epicsTime.h */
/* Author Jeffrey O. Hill */
/** \file epicsTime.h
* \brief EPICS time-stamps (epicsTimeStamp), epicsTime C++ class
* and C functions for handling wall-clock times.
* \author Jeffrey O. Hill
*/
#ifndef epicsTimehInclude
#define epicsTimehInclude
@@ -19,139 +22,294 @@
#include "osdTime.h"
#include "errMdef.h"
/* The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC */
/** \brief The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC */
#define POSIX_TIME_AT_EPICS_EPOCH 631152000u
/* epics time stamp for C interface*/
/** \brief EPICS time stamp, for use from C code.
*
* Because it uses an unsigned 32-bit integer to hold the seconds count, an
* epicsTimeStamp can safely represent time stamps until the year 2106.
*/
typedef struct epicsTimeStamp {
epicsUInt32 secPastEpoch; /* seconds since 0000 Jan 1, 1990 */
epicsUInt32 nsec; /* nanoseconds within second */
epicsUInt32 secPastEpoch; /**< \brief seconds since 0000 Jan 1, 1990 */
epicsUInt32 nsec; /**< \brief nanoseconds within second */
} epicsTimeStamp;
/*TS_STAMP is deprecated */
/** \brief Old time-stamp data type, deprecated.
* \deprecated TS_STAMP was provided for compatibility with Base-3.13 code.
* It will be removed in some future release of EPICS 7.
*/
#define TS_STAMP epicsTimeStamp
/** \struct timespec
* \brief Defined by POSIX Real Time
*
* This is defined by POSIX Real Time. It requires two mandatory fields:
* \li <tt>time_t tv_sec</tt> - Number of seconds since 1970 (The POSIX epoch)
* \li <tt>long tv_nsec</tt> - nanoseconds within a second
*/
struct timespec; /* POSIX real time */
/** \struct timeval
* \brief BSD and SRV5 Unix timestamp
*
* BSD and SRV5 Unix timestamp. It has two fields:
* \li <tt>time_t tv_sec</tt> - Number of seconds since 1970 (The POSIX epoch)
* \li <tt>time_t tv_nsec</tt> - nanoseconds within a second
*/
struct timeval; /* BSD */
/** \struct l_fp
* \brief Network Time Protocol timestamp
*
* Network Time Protocol timestamp. The fields are:
* \li \c lui - Number of seconds since 1900 (The NTP epoch)
* \li \c luf - Fraction of a second. For example 0x800000000 represents 1/2 second.
*/
struct l_fp; /* NTP timestamp */
#ifdef __cplusplus
/*
* extend ANSI C RTL "struct tm" to include nano seconds within a second
* and a struct tm that is adjusted for the local timezone
/** \brief C++ only ANSI C <tt>struct tm</tt> with nanoseconds, local timezone
*
* Extend ANSI C "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 */
struct tm ansi_tm; /**< \brief ANSI C time details */
unsigned long nSec; /**< \brief nanoseconds extension */
};
/*
* extend ANSI C RTL "struct tm" to includes nano seconds within a second
* and a struct tm that is adjusted for GMT (UTC)
/** \brief C++ only ANSI C <tt>sruct tm</tt> with nanoseconds, UTC
*
* Extend ANSI C "struct tm" to include nanoseconds 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 */
struct tm ansi_tm; /**< \brief ANSI C time details */
unsigned long nSec; /**< \brief nanoseconds extension */
};
/*
* wrapping this in a struct allows conversion to and
* from ANSI time_t but does not allow unexpected
* conversions to occur
/** \brief C++ only ANSI C time_t
*
* This is for converting to/from the ANSI C \c time_t. Since \c time_t
* is usually an elementary type providing a conversion operator from
* \c time_t to/from epicsTime could cause undesirable implicit
* conversions. Providing a conversion operator to/from the
* \c time_t_wrapper instead prevents implicit conversions.
*/
struct time_t_wrapper {
time_t ts;
};
/** \brief C++ Event number wrapper class
*
* Stores an event number for use by the epicsTime::getEvent() static
* class method.
*/
class epicsShareClass epicsTimeEvent
{
public:
epicsTimeEvent (const int &number);
operator int () const;
epicsTimeEvent (const int &number); /**< \brief Constructor */
operator int () const; /**< \brief Extractor */
private:
int eventNumber;
};
/** \brief C++ time stamp object
*
* Holds an EPICS time stamp, and provides conversion functions for both
* input and output from/to other types.
*
* \note Time conversions: The epicsTime 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.
*/
class epicsShareClass epicsTime
{
public:
/* exceptions */
/// \brief Exception: Time provider problem
class unableToFetchCurrentTime {};
/// \brief Exception: Bad field(s) in <tt>struct tm</tt>
class formatProblemWithStructTM {};
/** \brief The default constructor sets the time to the EPICS epoch. */
epicsTime ();
/** \brief Get time of event system event.
*
* Returns an epicsTime indicating when the associated event system
* event last occurred.
*/
static epicsTime getEvent ( const epicsTimeEvent & );
/** \brief Get current clock time
*
* Returns an epicsTime containing the current time. For example:
* \code{.cpp}
* epicsTime now = epicsTime::getCurrent();
* \endcode
*/
static epicsTime getCurrent ();
/** \brief Get current monotonic time
*
* Returns an epicsTime containing the current monotonic time, a
* high-resolution OS clock that counts at a steady rate, never
* going backwards or jumping forwards. This time is only useful
* for measuring time differences.
*/
static epicsTime getMonotonic ();
/* convert to and from EPICS epicsTimeStamp format */
/** \name epicsTimeStamp conversions
* Convert to and from EPICS epicsTimeStamp format
* @{ */
/** \brief Convert to epicsTimeStamp */
operator epicsTimeStamp () const;
/** \brief Construct from epicsTimeStamp */
epicsTime ( const epicsTimeStamp & ts );
/** \brief Assign from epicsTimeStamp */
epicsTime & operator = ( const epicsTimeStamp & );
/** @} */
/* convert to and from ANSI time_t */
/** \name ANSI C time_t conversions
* Convert to and from ANSI C \c time_t wrapper .
* @{ */
/** \brief Convert to ANSI C \c time_t */
operator time_t_wrapper () const;
/** \brief Construct from ANSI C \c time_t */
epicsTime ( const time_t_wrapper & );
/** \brief Assign from ANSI C \c time_t */
epicsTime & operator = ( const time_t_wrapper & );
/** @} */
/*
* convert to and from ANSI Cs "struct tm" (with nano seconds)
* adjusted for the local time zone
*/
/** \name ANSI C struct tm local-time conversions
* Convert to and from ANSI Cs <tt>struct tm</tt> (with nano seconds),
* adjusted for the local time zone.
* @{ */
/** \brief Convert to <tt>struct tm</tt> in local time zone */
operator local_tm_nano_sec () const;
/** \brief Construct from <tt>struct tm</tt> in local time zone */
epicsTime ( const local_tm_nano_sec & );
/** \brief Assign from <tt>struct tm</tt> in local time zone */
epicsTime & operator = ( const local_tm_nano_sec & );
/** @} */
/*
* convert to and from ANSI Cs "struct tm" (with nano seconds)
* adjusted for GM time (UTC)
*/
/** \name ANSI C struct tm UTC conversions
* Convert to and from ANSI Cs <tt>struct tm</tt> (with nano seconds),
* adjusted for Greenwich Mean Time (UTC).
* @{ */
/** \brief Convert to <tt>struct tm</tt> in UTC/GMT */
operator gm_tm_nano_sec () const;
/** \brief Construct from <tt>struct tm</tt> in UTC/GMT */
epicsTime ( const gm_tm_nano_sec & );
/** \brief Assign from <tt>struct tm</tt> in UTC */
epicsTime & operator = ( const gm_tm_nano_sec & );
/** @} */
/* convert to and from POSIX RTs "struct timespec" */
/** \name POSIX RT struct timespec conversions
* Convert to and from the POSIX RealTime <tt>struct timespec</tt>
* format.
* @{ */
/** \brief Convert to <tt>struct timespec</tt> */
operator struct timespec () const;
/** \brief Construct from <tt>struct timespec</tt> */
epicsTime ( const struct timespec & );
/** \brief Assign from <tt>struct timespec</tt> */
epicsTime & operator = ( const struct timespec & );
/** @} */
/* convert to and from BSDs "struct timeval" */
/** \name BSD's struct timeval conversions
* Convert to and from the BSD <tt>struct timeval</tt> format.
* @{ */
/** \brief Convert to <tt>struct timeval</tt> */
operator struct timeval () const;
/** \brief Construct from <tt>struct timeval</tt> */
epicsTime ( const struct timeval & );
/** \brief Assign from <tt>struct timeval</tt> */
epicsTime & operator = ( const struct timeval & );
/** @} */
/* convert to and from NTP timestamp format */
/** \name NTP timestamp conversions
* Convert to and from the NTP timestamp structure \c l_fp
* @{ */
/** \brief Convert to NTP format */
operator l_fp () const;
/** \brief Construct from NTP format */
epicsTime ( const l_fp & );
/** \brief Assign from NTP format */
epicsTime & operator = ( const l_fp & );
/** @} */
/* convert to and from WIN32s FILETIME (implemented only on WIN32) */
/** \name WIN32 FILETIME conversions
* Convert to and from WIN32s <tt> _FILETIME</tt>
* \note These are only implemented on Windows targets.
* @{ */
/** \brief Convert to Windows <tt>struct _FILETIME</tt> */
operator struct _FILETIME () const;
/** \brief Constuct from Windows <tt>struct _FILETIME</tt> */
epicsTime ( const struct _FILETIME & );
/** \brief Assign from Windows <tt>struct _FILETIME</tt> */
epicsTime & operator = ( const struct _FILETIME & );
/** @} */
/* arithmetic operators */
double operator- ( const epicsTime & ) const; /* returns seconds */
epicsTime operator+ ( const double & ) const; /* add rhs seconds */
epicsTime operator- ( const double & ) const; /* subtract rhs seconds */
epicsTime operator+= ( const double & ); /* add rhs seconds */
epicsTime operator-= ( const double & ); /* subtract rhs seconds */
/** \name Arithmetic operators
* Standard operators involving epicsTime objects and time differences
* which are always expressed as a \c double in seconds.
* @{ */
/// \brief \p lhs minus \p rhs, in seconds
double operator- ( const epicsTime & ) const;
/// \brief \p lhs plus rhs seconds
epicsTime operator+ ( const double & ) const;
/// \brief \p lhs minus rhs seconds
epicsTime operator- ( const double & ) const;
/// \brief add rhs seconds to \p lhs
epicsTime operator+= ( const double & );
/// \brief subtract rhs seconds from \p lhs
epicsTime operator-= ( const double & );
/** @} */
/* comparison operators */
bool operator == ( const epicsTime & ) const;
bool operator != ( const epicsTime & ) const;
bool operator <= ( const epicsTime & ) const;
bool operator < ( const epicsTime & ) const;
bool operator >= ( const epicsTime & ) const;
bool operator > ( const epicsTime & ) const;
/** \name Comparison operators
* Standard comparisons between epicsTime objects.
* @{ */
/// \brief \p lhs equals \p rhs
bool operator == ( const epicsTime & ) const;
/// \brief \p lhs not equal to \p rhs
bool operator != ( const epicsTime & ) const;
/// \brief \p rhs no later than \p lhs
bool operator <= ( const epicsTime & ) const;
/// \brief \p lhs was before \p rhs
bool operator < ( const epicsTime & ) const;
/// \brief \p rhs not before \p lhs
bool operator >= ( const epicsTime & ) const;
/// \brief \p lhs was after \p rhs
bool operator > ( const epicsTime & ) const;
/** @} */
/* convert current state to user-specified string */
/** \brief Convert to string in user-specified format
*
* This method extends the standard C library routine strftime().
* See your OS documentation for details about the standard routine.
* The epicsTime method adds support for printing the fractional
* portion of the time. It searches the format string for the
* sequence <tt>%0<i>n</i>f</tt> where \a n is the desired precision,
* and uses this format to convert the fractional seconds with the
* requested precision. For example:
* \code{.cpp}
* epicsTime time = epicsTime::getCurrent();
* char buf[30];
* time.strftime(buf, 30, "%Y-%m-%d %H:%M:%S.%06f");
* printf("%s\n", buf);
* \endcode
* This will print the current time in the format:
* \code
* 2001-01-26 20:50:29.813505
* \endcode
*/
size_t strftime ( char * pBuff, size_t bufLength, const char * pFormat ) const;
/* dump current state to standard out */
/** \brief Dump current state to standard out */
void show ( unsigned interestLevel ) const;
private:
@@ -173,98 +331,179 @@ private:
extern "C" {
#endif /* __cplusplus */
/* epicsTime routines return S_time_ error status values */
/** \name Return status values
* epicsTime routines return \c S_time_ error status values:
* @{
*/
/** \brief Success */
#define epicsTimeOK 0
/** \brief No time provider */
#define S_time_noProvider (M_time| 1) /*No time provider*/
/** \brief Bad event number */
#define S_time_badEvent (M_time| 2) /*Bad event number*/
/** \brief Invalid arguments */
#define S_time_badArgs (M_time| 3) /*Invalid arguments*/
/** \brief Out of memory */
#define S_time_noMemory (M_time| 4) /*Out of memory*/
/** \brief Provider not synchronized */
#define S_time_unsynchronized (M_time| 5) /*Provider not synchronized*/
#define S_time_timezone (M_time| 6) /*Invalid timeone*/
/** \brief Invalid timezone */
#define S_time_timezone (M_time| 6) /*Invalid timezone*/
/** \brief Time conversion error */
#define S_time_conversion (M_time| 7) /*Time conversion error*/
/** @} */
/*Some special values for eventNumber*/
/** \name epicsTimeEvent numbers
* Some special values for eventNumber:
* @{
*/
#define epicsTimeEventCurrentTime 0
#define epicsTimeEventBestTime -1
#define epicsTimeEventDeviceTime -2
/** @} */
/* These are implemented in the "generalTime" framework */
/** \name generalTime functions
* These are implemented in the "generalTime" framework:
* @{
*/
/** \brief Get current time into \p *pDest */
epicsShareFunc int epicsShareAPI epicsTimeGetCurrent ( epicsTimeStamp * pDest );
/** \brief Get time of event \p eventNumber into \p *pDest */
epicsShareFunc int epicsShareAPI epicsTimeGetEvent (
epicsTimeStamp *pDest, int eventNumber);
/** \brief Get monotonic time into \p *pDest */
epicsShareFunc int epicsTimeGetMonotonic ( epicsTimeStamp * pDest );
/** @} */
/* These are callable from an Interrupt Service Routine */
/** \name ISR-callable
* These routines may be called from an Interrupt Service Routine, and
* will return a value from the last current time or event time provider
* that sucessfully returned a result from the equivalent non-ISR routine.
* @{
*/
/** \brief Get current time into \p *pDest (ISR-safe) */
epicsShareFunc int epicsTimeGetCurrentInt(epicsTimeStamp *pDest);
/** \brief Get time of event \p eventNumber into \p *pDest (ISR-safe) */
epicsShareFunc int epicsTimeGetEventInt(epicsTimeStamp *pDest, int eventNumber);
/** @} */
/* convert to and from ANSI C's "time_t" */
/** \name ANSI C time_t conversions
* Convert to and from ANSI C \c time_t
* @{
*/
/** \brief Convert epicsTimeStamp to ANSI C \c time_t */
epicsShareFunc int epicsShareAPI epicsTimeToTime_t (
time_t * pDest, const epicsTimeStamp * pSrc );
/** \brief Convert ANSI C \c time_t to epicsTimeStamp */
epicsShareFunc int epicsShareAPI epicsTimeFromTime_t (
epicsTimeStamp * pDest, time_t src );
/** @} */
/* convert to and from ANSI C's "struct tm" with nano seconds */
/** \name ANSI C struct tm conversions
* Convert to and from ANSI C's <tt>struct tm</tt> with nanoseconds
* @{
*/
/** \brief Convert epicsTimeStamp to <tt>struct tm</tt> in local time zone */
epicsShareFunc int epicsShareAPI epicsTimeToTM (
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
/** \brief Convert epicsTimeStamp to <tt>struct tm</tt> in UTC/GMT */
epicsShareFunc int epicsShareAPI epicsTimeToGMTM (
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
/** \brief Set epicsTimeStamp from <tt>struct tm</tt> in local time zone */
epicsShareFunc int epicsShareAPI epicsTimeFromTM (
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
/** \brief Set epicsTimeStamp from <tt>struct tm</tt> in UTC/GMT */
epicsShareFunc int epicsShareAPI epicsTimeFromGMTM (
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
/** @} */
/* convert to and from POSIX RT's "struct timespec" */
/** \name POSIX RT struct timespec conversions
* Convert to and from the POSIX RealTime <tt>struct timespec</tt>
* format.
* @{ */
/** \brief Convert epicsTimeStamp to <tt>struct timespec</tt> */
epicsShareFunc int epicsShareAPI epicsTimeToTimespec (
struct timespec * pDest, const epicsTimeStamp * pSrc );
/** \brief Set epicsTimeStamp from <tt>struct timespec</tt> */
epicsShareFunc int epicsShareAPI epicsTimeFromTimespec (
epicsTimeStamp * pDest, const struct timespec * pSrc );
/** @} */
/* convert to and from BSD's "struct timeval" */
/** \name BSD's struct timeval conversions
* Convert to and from the BSD <tt>struct timeval</tt> format.
* @{ */
/** \brief Convert epicsTimeStamp to <tt>struct timeval</tt> */
epicsShareFunc int epicsShareAPI epicsTimeToTimeval (
struct timeval * pDest, const epicsTimeStamp * pSrc );
/** \brief Set epicsTimeStamp from <tt>struct timeval</tt> */
epicsShareFunc int epicsShareAPI epicsTimeFromTimeval (
epicsTimeStamp * pDest, const struct timeval * pSrc );
/** @} */
/*arithmetic operations */
/** \name Arithmetic operations
* Arithmetic operations on epicsTimeStamp objects and time differences
* which are always expressed as a \c double in seconds.
* @{ */
/** \brief Time difference between \p left and \p right in seconds. */
epicsShareFunc double epicsShareAPI epicsTimeDiffInSeconds (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight );/* left - right */
/** \brief Add some number of seconds to \p dest */
epicsShareFunc void epicsShareAPI epicsTimeAddSeconds (
epicsTimeStamp * pDest, double secondsToAdd ); /* adds seconds to *pDest */
/** @} */
/*comparison operations: returns (0,1) if (false,true) */
/** \name Comparison operators
* Comparisons between epicsTimeStamp objects, returning 0=false, 1=true.
* @{ */
/** \brief \p left equals \p right */
epicsShareFunc int epicsShareAPI epicsTimeEqual (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
/** \brief \p left not equal to \p right */
epicsShareFunc int epicsShareAPI epicsTimeNotEqual (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
/** \brief \p left was before \p right */
epicsShareFunc int epicsShareAPI epicsTimeLessThan (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left < right */
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
/** \brief \p right was no later than \p left */
epicsShareFunc int epicsShareAPI epicsTimeLessThanEqual (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left <= right) */
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
/** \brief \p left was after \p right */
epicsShareFunc int epicsShareAPI epicsTimeGreaterThan (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left > right */
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
/** \brief \p right was not before \p left */
epicsShareFunc int epicsShareAPI epicsTimeGreaterThanEqual (
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left >= right */
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
/** @} */
/*convert to ASCII string */
/** \brief Convert epicsTimeStamp to string. See epicsTime::strftime() */
epicsShareFunc size_t epicsShareAPI epicsTimeToStrftime (
char * pBuff, size_t bufLength, const char * pFormat, const epicsTimeStamp * pTS );
/* dump current state to standard out */
/** \brief Dump current state to stdout */
epicsShareFunc void epicsShareAPI epicsTimeShow (
const epicsTimeStamp *, unsigned interestLevel );
/* OS dependent reentrant versions of the ANSI C interface because */
/* vxWorks gmtime_r interface does not match POSIX standards */
/** \name Reentrant time_t to struct tm conversions
* OS-specific reentrant versions of the ANSI C interface because the
* vxWorks \c gmtime_r interface does not match POSIX standards
* @{ */
/** \brief Break down a \c time_t into a <tt>struct tm</tt> in the local timezone */
epicsShareFunc int epicsShareAPI epicsTime_localtime ( const time_t * clock, struct tm * result );
/** \brief Break down a \c time_t into a <tt>struct tm</tt> in the UTC timezone */
epicsShareFunc int epicsShareAPI epicsTime_gmtime ( const time_t * clock, struct tm * result );
/** @} */
/* Advertised monotonic counter resolution (may not be accurate).
* Minimum non-zero difference between two calls to epicsMonotonicGet()
/** \name Monotonic time routines
* @{ */
/** \brief Monotonic time resolution, may not be accurate. Returns the
* minimum non-zero time difference between two calls to epicsMonotonicGet()
* in units of nanoseconds.
*/
epicsShareFunc epicsUInt64 epicsMonotonicResolution(void);
/* Fetch monotonic counter, return is nano-seconds since an unspecified time */
/** \brief Fetch monotonic counter, returns the number of nanoseconds since
* some unspecified time. */
epicsShareFunc epicsUInt64 epicsMonotonicGet(void);
/** @} */
#ifdef EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE
epicsShareFunc void osdMonotonicInit(void);
@@ -366,4 +605,3 @@ inline epicsTime & epicsTime::operator = ( const time_t_wrapper & rhs )
#endif /* __cplusplus */
#endif /* epicsTimehInclude */

View File

@@ -25,13 +25,13 @@ extern "C" {
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
* \return NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
* \return NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);

View File

@@ -24,13 +24,13 @@ extern "C" {
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
\return NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
\return NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);

View File

@@ -4,8 +4,14 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Michael Davidsaver <mdavidsaver@bnl.gov>
/**
* \file epicsMMIODef.h
* \brief Memory Mapped I/O
*
* Definitions related to Memory Mapped I/O
*
* \author Michael Davidsaver <mdavidsaver@bnl.gov>
* @ingroup mmio
*/
#ifndef EPICSMMIODEF_H
@@ -26,7 +32,7 @@
*@{
*/
/** @brief Read a single byte.
/** \brief Read a single byte.
*/
static EPICS_ALWAYS_INLINE
epicsUInt8
@@ -35,7 +41,7 @@ ioread8(volatile void* addr)
return *(volatile epicsUInt8*)(addr);
}
/** @brief Write a single byte.
/** \brief Write a single byte.
*/
static EPICS_ALWAYS_INLINE
void
@@ -44,7 +50,7 @@ iowrite8(volatile void* addr, epicsUInt8 val)
*(volatile epicsUInt8*)(addr) = val;
}
/** @brief Read two bytes in host order.
/** \brief Read two bytes in host order.
* Not byte swapping
*/
static EPICS_ALWAYS_INLINE
@@ -54,7 +60,7 @@ nat_ioread16(volatile void* addr)
return *(volatile epicsUInt16*)(addr);
}
/** @brief Write two byte in host order.
/** \brief Write two byte in host order.
* Not byte swapping
*/
static EPICS_ALWAYS_INLINE
@@ -64,7 +70,7 @@ nat_iowrite16(volatile void* addr, epicsUInt16 val)
*(volatile epicsUInt16*)(addr) = val;
}
/** @brief Read four bytes in host order.
/** \brief Read four bytes in host order.
* Not byte swapping
*/
static EPICS_ALWAYS_INLINE
@@ -74,7 +80,7 @@ nat_ioread32(volatile void* addr)
return *(volatile epicsUInt32*)(addr);
}
/** @brief Write four byte in host order.
/** \brief Write four byte in host order.
* Not byte swapping
*/
static EPICS_ALWAYS_INLINE
@@ -151,50 +157,50 @@ bswap32(epicsUInt32 value)
# error Unable to determine native byte order
#endif
/** @def bswap16
* @brief Unconditional two byte swap
/** \def bswap16
* \brief Unconditional two byte swap
*/
/** @def bswap32
* @brief Unconditional four byte swap
/** \def bswap32
* \brief Unconditional four byte swap
*/
/** @def be_ioread16
* @brief Read two byte in big endian order.
/** \def be_ioread16
* \brief Read two byte in big endian order.
*/
/** @def be_iowrite16
* @brief Write two byte in big endian order.
/** \def be_iowrite16
* \brief Write two byte in big endian order.
*/
/** @def be_ioread32
* @brief Read four byte in big endian order.
/** \def be_ioread32
* \brief Read four byte in big endian order.
*/
/** @def be_iowrite32
* @brief Write four byte in big endian order.
/** \def be_iowrite32
* \brief Write four byte in big endian order.
*/
/** @def le_ioread16
* @brief Read two byte in little endian order.
/** \def le_ioread16
* \brief Read two byte in little endian order.
*/
/** @def le_iowrite16
* @brief Write two byte in little endian order.
/** \def le_iowrite16
* \brief Write two byte in little endian order.
*/
/** @def le_ioread32
* @brief Read four byte in little endian order.
/** \def le_ioread32
* \brief Read four byte in little endian order.
*/
/** @def le_iowrite32
* @brief Write four byte in little endian order.
/** \def le_iowrite32
* \brief Write four byte in little endian order.
*/
/** @ingroup mmio
*@{
*/
/** @brief Explicit read memory barrier
/** \brief Explicit read memory barrier
* Prevents reordering of reads around it.
*/
#define rbarr() do{}while(0)
/** @brief Explicit write memory barrier
/** \brief Explicit write memory barrier
* Prevents reordering of writes around it.
*/
#define wbarr() do{}while(0)
/** @brief Explicit read/write memory barrier
/** \brief Explicit read/write memory barrier
* Prevents reordering of reads or writes around it.
*/
#define rwbarr() do{}while(0)
@@ -233,30 +239,30 @@ bswap32(epicsUInt32 value)
*
*@b PCI
*
@code
\code
be_iowrite16(base+off, 14);
var = be_ioread16(base+off);
@endcode
\endcode
*
*@b VME
*
@code
\code
nat_iowrite16(base+off, 14);
var = nat_ioread16(base+off);
@endcode
\endcode
*
*@subsection mmioexle Little endian device
*
*@b PCI
@code
\code
le_iowrite16(base+off, 14);
var = le_ioread16(base+off);
@endcode
\endcode
*@b VME
@code
\code
nat_iowrite16(base+off, bswap16(14));
var = bswap16(nat_iowrite16(base+off));
@endcode
\endcode
*This difference arises because VME bridges implement hardware byte
*swapping on little endian systems, while PCI bridges do not.
*Software accessing PCI devices must know if byte swapping is required.
@@ -268,7 +274,9 @@ bswap32(epicsUInt32 value)
*
*Software accessing VME must @b not do conditional swapping.
*
*@note All read and write operations have an implicit read or write barrier.
*\note All read and write operations have an implicit read or write barrier.
*/
/** @} */
#endif /* EPICSMMIODEF_H */

View File

@@ -7,16 +7,15 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/**\file osiPoolStatus.h
* \author Jeff Hill
* \brief Functions to check the state of the system memory pool.
*
**/
#ifndef INC_osiPoolStatus_H
#define INC_osiPoolStatus_H
/*
* Author: Jeff Hill
*
* Functions which interrogate the state of the system wide pool
*
*/
#include <stdlib.h>
#include "shareLib.h"
@@ -24,12 +23,17 @@
extern "C" {
#endif
/*
* tests to see if there is sufficent space for a block of the requested size
* along with whatever additional free space is necessary to keep the system running
* reliably
/**\brief Checks if a memory block of a specific size can be safely allocated.
*
* this routine is called quite frequently so an efficent implementation is important
* The meaning of "safely allocated" is target-specific, some additional free
* space is usually necessary to keep the system running reliably.
* On vxWorks this returns True if at least 100000 bytes is free.
*
* \note This routine is called quite frequently by the IOC so an efficent
* implementation is important.
*
* \param contiguousBlockSize Block size to check.
* \return True if the requested memory should be available.
*/
epicsShareFunc int epicsShareAPI osiSufficentSpaceInPool ( size_t contiguousBlockSize );

View File

@@ -7,11 +7,21 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Marty Kraimer Date: 15JUL99
* Eric Norum
* Ralph Lange <Ralph.Lange@gmx.de>
/**
* \file epicsRingBytes.h
* \author Marty Kraimer, Eric Norum, Ralph Lange
* \brief A circular buffer to store bytes
*
* \details
* EpicsRingBytes provides a C API for creating and using ring buffers
* (first in first out circular buffers) that store bytes. The unlocked
* variant is designed so that one writer thread and one reader thread
* can access the ring simultaneously without requiring mutual exclusion.
* The locked variant uses an epicsSpinLock, and works with any numbers of
* writer and reader threads.
* \note If there is only one writer it is not necessary to lock for puts.
* If there is a single reader it is not necessary to lock for gets.
* epicsRingBytesLocked uses a spinlock.
*/
#ifndef INCepicsRingBytesh
@@ -23,35 +33,103 @@ extern "C" {
#include "shareLib.h"
/** \brief An identifier for a ring buffer */
typedef void *epicsRingBytesId;
typedef void const *epicsRingBytesIdConst;
/**
* \brief Create a new ring buffer
* \param nbytes Size of ring buffer to create
* \return Ring buffer Id or NULL on failure
*/
epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesCreate(int nbytes);
/* Same, but secured by a spinlock */
/**
* \brief Create a new ring buffer, secured by a spinlock
* \param nbytes Size of ring buffer to create
* \return Ring buffer Id or NULL on failure
*/
epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesLockedCreate(int nbytes);
/**
* \brief Delete the ring buffer and free any associated memory
* \param id RingbufferID returned by epicsRingBytesCreate()
*/
epicsShareFunc void epicsShareAPI epicsRingBytesDelete(epicsRingBytesId id);
/**
* \brief Read data out of the ring buffer
* \param id RingbufferID returned by epicsRingBytesCreate()
* \param value Where to put the data fetched from the buffer
* \param nbytes Maximum number of bytes to get
* \return The number of bytes actually fetched
*/
epicsShareFunc int epicsShareAPI epicsRingBytesGet(
epicsRingBytesId id, char *value,int nbytes);
/**
* \brief Write data into the ring buffer
* \param id RingbufferID returned by epicsRingBytesCreate()
* \param value Source of the data to be put into the buffer
* \param nbytes How many bytes to put
* \return The number of bytes actually stored, zero if not enough space
*/
epicsShareFunc int epicsShareAPI epicsRingBytesPut(
epicsRingBytesId id, char *value,int nbytes);
/**
* \brief Make the ring buffer empty
* \param id RingbufferID returned by epicsRingBytesCreate()
* \note Should only be used when both gets and puts are locked out.
*/
epicsShareFunc void epicsShareAPI epicsRingBytesFlush(epicsRingBytesId id);
/**
* \brief Return the number of free bytes in the ring buffer
* \param id RingbufferID returned by epicsRingBytesCreate()
* \return The number of free bytes in the ring buffer
*/
epicsShareFunc int epicsShareAPI epicsRingBytesFreeBytes(epicsRingBytesId id);
/**
* \brief Return the number of bytes currently stored in the ring buffer
* \param id RingbufferID returned by epicsRingBytesCreate()
* \return The number of bytes currently stored in the ring buffer
*/
epicsShareFunc int epicsShareAPI epicsRingBytesUsedBytes(epicsRingBytesId id);
/**
* \brief Return the size of the ring buffer
* \param id RingbufferID returned by epicsRingBytesCreate()
* \return Return the size of the ring buffer, i.e., nbytes specified in
* the call to epicsRingBytesCreate().
*/
epicsShareFunc int epicsShareAPI epicsRingBytesSize(epicsRingBytesId id);
/**
* \brief Test if the ring buffer is currently empty.
* \param id RingbufferID returned by epicsRingBytesCreate()
* \return 1 if the buffer is empty, otherwise 0
*/
epicsShareFunc int epicsShareAPI epicsRingBytesIsEmpty(epicsRingBytesId id);
/**
* \brief Test if the ring buffer is currently full.
* \param id RingbufferID returned by epicsRingBytesCreate()
* \return 1 if the buffer is full, otherwise 0
*/
epicsShareFunc int epicsShareAPI epicsRingBytesIsFull(epicsRingBytesId id);
/**
* \brief See how full a ring buffer has been since it was last checked.
*
* Returns the maximum amount of data the ring buffer has held in bytes
* since the water mark was last reset. A new ring buffer starts with a
* water mark of 0.
* \param id RingbufferID returned by epicsRingBytesCreate()
* \return Actual Highwater mark
*/
epicsShareFunc int epicsShareAPI epicsRingBytesHighWaterMark(epicsRingBytesIdConst id);
/**
* \brief Reset the Highwater mark of the ring buffer.
*
* The Highwater mark will be set to the current usage
* \param id RingbufferID returned by epicsRingBytesCreate()
*/
epicsShareFunc void epicsShareAPI epicsRingBytesResetHighWaterMark(epicsRingBytesId id);
#ifdef __cplusplus
}
#endif
/* NOTES
If there is only one writer it is not necessary to lock for put
If there is a single reader it is not necessary to lock for puts
epicsRingBytesLocked uses a spinlock.
*/
#endif /* INCepicsRingBytesh */

View File

@@ -7,40 +7,92 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Marty Kraimer Date: 15JUL99
* Ralph Lange <Ralph.Lange@gmx.de>
/**
* \file epicsRingPointer.h
* \brief A circular buffer to store pointers
* \author Marty Kraimer, Ralph Lange
*
* \details
* epicsRingPointer.h provides both C and C++ APIs for creating and using ring
* buffers (first in first out circular buffers) that store pointers. The
* unlocked kind is designed so that one writer thread and one reader thread
* can access the ring simultaneously without requiring mutual exclusion. The
* locked variant uses an epicsSpinLock, and works with any numbers of writer
* and reader threads.
* \note If there is only one writer it is not necessary to lock pushes.
* If there is a single reader it is not necessary to lock pops.
* epicsRingPointerLocked uses a spinlock.
*/
#ifndef INCepicsRingPointerh
#define INCepicsRingPointerh
/* NOTES
* If there is only one writer it is not necessary to lock push
* If there is a single reader it is not necessary to lock pop
*
* epicsRingPointerLocked uses a spinlock.
*/
#include "epicsSpin.h"
#include "shareLib.h"
#ifdef __cplusplus
/**
* \brief A C++ template class providing methods for creating and using a ring
* buffer (a first in, first out circular buffer) that stores pointers to
* objects of the template type.
*/
template <class T>
class epicsRingPointer {
public: /* Functions */
/**\brief Constructor
* \param size Maximum number of elements (pointers) that can be stored
* \param locked If true, the spin lock secured variant is created
*/
epicsRingPointer(int size, bool locked);
/**\brief Destructor
*/
~epicsRingPointer();
/**\brief Push a new entry on the ring
* \return True on success, False if the buffer was full
*/
bool push(T *p);
/**\brief Take an element off the ring
* \return The element, or NULL if the ring was empty
*/
T* pop();
/**\brief Remove all elements from the ring.
* \note If this operation is performed on a ring buffer of the
* unsecured kind, all access to the ring should be locked.
*/
void flush();
/**\brief Get how much free space remains in the ring
* \return The number of additional elements the ring could hold.
*/
int getFree() const;
/**\brief Get how many elements are stored on the ring
* \return The number of elements currently stored.
*/
int getUsed() const;
/**\brief Get the size of the ring
* \return The \c size specified when the ring was created.
*/
int getSize() const;
/**\brief Test if the ring is currently empty
* \return True if the ring is empty, otherwise false.
*/
bool isEmpty() const;
/**\brief Test if the ring is currently full
* \return True if the ring is full, otherwise false.
*/
bool isFull() const;
/**\brief See how full the ring has got since it was last checked.
*
* Returns the maximum number of elements the ring
* buffer has held since the water mark was last reset.
* A new ring buffer starts with a water mark of 0.
* \return Actual highwater mark
*/
int getHighWaterMark() const;
/**\brief Reset high water mark
*
* High water mark will be set to the current usage
*/
void resetHighWaterMark();
private: /* Prevent compiler-generated member functions */
@@ -62,24 +114,93 @@ private: /* Data */
extern "C" {
#endif /*__cplusplus */
/** \brief An identifier for the C API to a ring buffer storing pointers */
typedef void *epicsRingPointerId;
typedef void const *epicsRingPointerIdConst;
/**
* \brief Create a new ring buffer
* \param size Size of ring buffer to create
* \return Ring buffer identifier or NULL on failure
*/
epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size);
/* Same, but secured by a spinlock */
/**
* \brief Create a new ring buffer, secured by a spinlock
* \param size Size of ring buffer to create
* \return Ring buffer identifier or NULL on failure
*/
epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerLockedCreate(int size);
/**
* \brief Delete the ring buffer and free any associated memory
* \param id Ring buffer identifier
*/
epicsShareFunc void epicsShareAPI epicsRingPointerDelete(epicsRingPointerId id);
/*ringPointerPush returns (0,1) if p (was not, was) put on ring*/
/**
* \brief Push pointer into the ring buffer
* \param id Ring buffer identifier
* \param p Pointer to be pushed to the ring
* \return 1 if the pointer was successfully pushed, 0 if the buffer was full
*/
epicsShareFunc int epicsShareAPI epicsRingPointerPush(epicsRingPointerId id,void *p);
/*ringPointerPop returns 0 if ring is empty*/
/**
* \brief Take an element off the ring
* \param id Ring buffer identifier
* \return The pointer from the buffer, or NULL if the ring was empty
*/
epicsShareFunc void* epicsShareAPI epicsRingPointerPop(epicsRingPointerId id) ;
/**
* \brief Remove all elements from the ring
* \param id Ring buffer identifier
* \note If this operation is performed on a ring buffer of the unsecured
* kind, all access to the ring should be locked.
*/
epicsShareFunc void epicsShareAPI epicsRingPointerFlush(epicsRingPointerId id);
/**
* \brief Return the amount of empty space in the ring buffer
* \param id Ring buffer identifier
* \return The number of additional elements it could hold.
*/
epicsShareFunc int epicsShareAPI epicsRingPointerGetFree(epicsRingPointerId id);
/**
* \brief Return the number of elements stored in the ring buffer
* \param id Ring buffer identifier
* \return The number of elements stored in the ring buffer
*/
epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id);
/**
* \brief Return the size of the ring
* \param id Ring buffer identifier
* \return The size of the ring buffer, i.e. the value of \c size
* given when the ring was created.
*/
epicsShareFunc int epicsShareAPI epicsRingPointerGetSize(epicsRingPointerId id);
/**
* \brief Check if the ring buffer is currently empty
* \param id Ring buffer identifier
* \return 1 if the ring is empty, otherwise 0
*/
epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id);
/**
* \brief Check if the ring buffer is currently full
* \param id Ring buffer identifier
* \return 1 if the ring buffer is full, otherwise 0
*/
epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id);
/**
* \brief Get the Highwater mark of the ring buffer
*
* Returns the largest number of elements the ring buffer has held since
* the water mark was last reset. A new ring buffer starts with a
* water mark of 0.
* \param id Ring buffer identifier
* \return Actual Highwater mark
*/
epicsShareFunc int epicsShareAPI epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id);
/**
* \brief Reset the Highwater mark of the ring buffer
*
* The Highwater mark will be set to the current usage
* \param id Ring buffer identifier
*/
epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPointerId id);
/* This routine was incorrectly named in previous releases */
@@ -92,12 +213,6 @@ epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPo
/* INLINE FUNCTIONS */
/* Algorithm note
* Space is allocated for one additional element.
* A put request is rejected if the it would cause nextPush to equal nextPop
* The algorithm does not require locking puts for a single writer
* or locking of gets for a single reader
*/
#ifdef __cplusplus
template <class T>

View File

@@ -16,8 +16,12 @@
/**
* \file yajl_alloc.h
* default memory allocation routines for yajl which use malloc/realloc and
* free
* \brief Memory allocation macros for yajl
* \author Lloyd Hilaiel
*
* These macros are used inside YAJL instead of directly calling
* malloc(), realloc() or free(). They call the equivalent method
* in their \ref yajl_alloc_funcs parameter \a afs.
*/
#ifndef __YAJL_ALLOC_H__

View File

@@ -26,47 +26,54 @@
extern "C" {
#endif
/** \file yajl_common.h
* \brief Common routines and macros used by other YAJL APIs.
* \author Lloyd Hilaiel
*/
/** YAJL API history in brief
*
* Originally macro not defined
* YAJL 1.0.12
* Bundled with EPICS Base 3.15.0.1
* This macro was not defined in the
* YAJL 1.0.12 version that was
* bundled with EPICS Base 3.15.0.1
*
* YAJL 2.1.0
* Changes argument type for yajl_integer() from 'int' to 'long long'
* Changes argument type for yajl_string() and yajl_map_key() from 'unsigned' to 'size_t'
* Replacement of struct yajl_parser_config with yajl_config()
* Replacement of yajl_parse_complete() with yajl_complete_parse()
* \li Changes argument type for yajl_integer() from \c int to \c long \c long
* \li Changes argument type for yajl_string() and yajl_map_key() from \c unsigned to \c size_t
* \li Replacement of struct yajl_parser_config with yajl_config()
* \li Replacement of yajl_parse_complete() with yajl_complete_parse()
*/
#define EPICS_YAJL_VERSION VERSION_INT(2,1,0,0)
/** Maximum generation depth for YAJL's JSON generation routines */
#define YAJL_MAX_DEPTH 128
/** Symbol decoration for Microsoft builds */
#define YAJL_API LIBCOM_API
/** pointer to a malloc function, supporting client overriding memory
/** Pointer to a malloc() function, supporting client overriding memory
* allocation routines */
typedef void * (*yajl_malloc_func)(void *ctx, size_t sz);
/** pointer to a free function, supporting client overriding memory
/** Pointer to a free() function, supporting client overriding memory
* allocation routines */
typedef void (*yajl_free_func)(void *ctx, void * ptr);
/** pointer to a realloc function which can resize an allocation. */
/** Pointer to a realloc() function which can resize an allocation. */
typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz);
/** A structure which can be passed to yajl_*_alloc routines to allow the
* client to specify memory allocation functions to be used. */
typedef struct
{
/** pointer to a function that can allocate uninitialized memory */
/** Pointer to a function that can allocate uninitialized memory */
yajl_malloc_func malloc;
/** pointer to a function that can resize memory allocations */
/** Pointer to a function that can resize memory allocations */
yajl_realloc_func realloc;
/** pointer to a function that can free memory allocated using
/** Pointer to a function that can free memory allocated using
* reallocFunction or mallocFunction */
yajl_free_func free;
/** a context pointer that will be passed to above allocation routines */
/** A context pointer that will be passed to above allocation routines */
void * ctx;
} yajl_alloc_funcs;

View File

@@ -16,7 +16,8 @@
/**
* \file yajl_gen.h
* Interface to YAJL's JSON generation facilities.
* \brief Interface to YAJL's JSON generation facilities.
* \author Lloyd Hilaiel
*/
#ifndef __YAJL_GEN_H__
@@ -27,49 +28,49 @@
#ifdef __cplusplus
extern "C" {
#endif
/** generator status codes */
/** Generator status codes */
typedef enum {
/** no error */
/** No error */
yajl_gen_status_ok = 0,
/** at a point where a map key is generated, a function other than
* yajl_gen_string was called */
/** At a point where a map key is generated, a function other than
* yajl_gen_string() was called */
yajl_gen_keys_must_be_strings,
/** YAJL's maximum generation depth was exceeded. see
* YAJL_MAX_DEPTH */
* \ref YAJL_MAX_DEPTH */
yajl_max_depth_exceeded,
/** A generator function (yajl_gen_XXX) was called while in an error
* state */
yajl_gen_in_error_state,
/** A complete JSON document has been generated */
yajl_gen_generation_complete,
/** yajl_gen_double was passed an invalid floating point value
/** yajl_gen_double() was passed an invalid floating point value
* (infinity or NaN). */
yajl_gen_invalid_number,
/** A print callback was passed in, so there is no internal
* buffer to get from */
yajl_gen_no_buf,
/** returned from yajl_gen_string() when the yajl_gen_validate_utf8
/** Returned from yajl_gen_string() when the yajl_gen_validate_utf8()
* option is enabled and an invalid was passed by client code.
*/
yajl_gen_invalid_string
} yajl_gen_status;
/** an opaque handle to a generator */
/** An opaque handle to a generator */
typedef struct yajl_gen_t * yajl_gen;
/** a callback used for "printing" the results. */
/** A callback used for "printing" the results. */
typedef void (*yajl_print_t)(void * ctx,
const char * str,
size_t len);
/** configuration parameters for the parser, these may be passed to
/** Configuration parameters for the parser, these may be passed to
* yajl_gen_config() along with option specific argument(s). In general,
* all configuration parameters default to *off*. */
typedef enum {
/** generate indented (beautiful) output */
/** Generate indented (beautiful) output */
yajl_gen_beautify = 0x01,
/**
* Set an indent string which is used when yajl_gen_beautify
* Set an indent string which is used when yajl_gen_beautify()
* is enabled. Maybe something like \\t or some number of
* spaces. The default is four spaces ' '.
*/
@@ -77,11 +78,12 @@ extern "C" {
/**
* Set a function and context argument that should be used to
* output generated json. the function should conform to the
* yajl_print_t prototype while the context argument is a
* yajl_print_t() prototype while the context argument is a
* void * of your choosing.
*
* example:
* Example: \code{.cpp}
* yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr);
* \endcode
*/
yajl_gen_print_callback = 0x04,
/**
@@ -91,7 +93,7 @@ extern "C" {
*/
yajl_gen_validate_utf8 = 0x08,
/**
* the forward solidus (slash or '/' in human) is not required to be
* The forward solidus (slash or '/' in human) is not required to be
* escaped in json text. By default, YAJL will not escape it in the
* iterest of saving bytes. Setting this flag will cause YAJL to
* always escape '/' in generated JSON strings.
@@ -99,51 +101,62 @@ extern "C" {
yajl_gen_escape_solidus = 0x10
} yajl_gen_option;
/** allow the modification of generator options subsequent to handle
* allocation (via yajl_alloc)
/** Allow the modification of generator options subsequent to handle
* allocation (via yajl_alloc())
* \returns zero in case of errors, non-zero otherwise
*/
YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...);
/** allocate a generator handle
* \param allocFuncs an optional pointer to a structure which allows
/** Allocate a generator handle
* \param allocFuncs An optional pointer to a structure which allows
* the client to overide the memory allocation
* used by yajl. May be NULL, in which case
* malloc/free/realloc will be used.
* malloc(), free() and realloc() will be used.
*
* \returns an allocated handle on success, NULL on failure (bad params)
*/
YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs);
/** free a generator handle */
/** Free a generator handle */
YAJL_API void yajl_gen_free(yajl_gen handle);
/** Generate an integer number. */
YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number);
/** generate a floating point number. number may not be infinity or
/** Generate a floating point number. \p number may not be infinity or
* NaN, as these have no representation in JSON. In these cases the
* generator will return 'yajl_gen_invalid_number' */
* generator will return \ref yajl_gen_invalid_number */
YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number);
/** Generate a number from the string given in \p num. */
YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand,
const char * num,
size_t len);
/** Generate a string value or map key from \p str. */
YAJL_API yajl_gen_status yajl_gen_string(yajl_gen hand,
const unsigned char * str,
size_t len);
/** Generate a \c null value. */
YAJL_API yajl_gen_status yajl_gen_null(yajl_gen hand);
/** Generate a \c true or \c false value from \p boolean. */
YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean);
/** Start generating a JSON map. This should be followed by calls to
* yajl_gen_string() to provide a key and another yajl_gen routine
* to provide the value associated with that key. */
YAJL_API yajl_gen_status yajl_gen_map_open(yajl_gen hand);
/** Finish generating a JSON map. */
YAJL_API yajl_gen_status yajl_gen_map_close(yajl_gen hand);
/** Start generating a JSON array. */
YAJL_API yajl_gen_status yajl_gen_array_open(yajl_gen hand);
/** Finish generating a JSON array. */
YAJL_API yajl_gen_status yajl_gen_array_close(yajl_gen hand);
/** access the null terminated generator buffer. If incrementally
* outputing JSON, one should call yajl_gen_clear to clear the
/** Access the null terminated generator buffer. If incrementally
* outputing JSON, one should call yajl_gen_clear() to clear the
* buffer. This allows stream generation. */
YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand,
const unsigned char ** buf,
size_t * len);
/** clear yajl's output buffer, but maintain all internal generation
/** Clear yajl's output buffer, but maintain all internal generation
* state. This function will not "reset" the generator state, and is
* intended to enable incremental JSON outputing. */
YAJL_API void yajl_gen_clear(yajl_gen hand);

View File

@@ -16,7 +16,8 @@
/**
* \file yajl_parse.h
* Interface to YAJL's JSON stream parsing facilities.
* \brief Interface to YAJL's JSON stream parsing facilities.
* \author Lloyd Hilaiel
*/
#ifndef __YAJL_PARSE_H__
@@ -27,47 +28,45 @@
#ifdef __cplusplus
extern "C" {
#endif
/** error codes returned from this interface */
/** Error codes returned from this interface */
typedef enum {
/** no error was encountered */
/** No error was encountered */
yajl_status_ok,
/** a client callback returned zero, stopping the parse */
/** A client callback returned zero, stopping the parse */
yajl_status_client_canceled,
/** An error occured during the parse. Call yajl_get_error for
/** An error occured during the parse. Call yajl_get_error() for
* more information about the encountered error */
yajl_status_error
} yajl_status;
/** attain a human readable, english, string for an error */
/** Attain a human readable, english, string for an error */
YAJL_API const char * yajl_status_to_string(yajl_status code);
/** an opaque handle to a parser */
/** An opaque handle to a parser */
typedef struct yajl_handle_t * yajl_handle;
/** yajl is an event driven parser. this means as json elements are
/** YAJL is an event driven parser. This means as json elements are
* parsed, you are called back to do something with the data. The
* functions in this table indicate the various events for which
* you will be called back. Each callback accepts a "context"
* pointer, this is a void * that is passed into the yajl_parse
* pointer, this is a void * that is passed into the yajl_parse()
* function which the client code may use to pass around context.
*
* All callbacks return an integer. If non-zero, the parse will
* continue. If zero, the parse will be canceled and
* yajl_status_client_canceled will be returned from the parse.
* yajl_status_client_canceled() will be returned from the parse.
*
* \attention {
* \attention
* A note about the handling of numbers:
*
* yajl will only convert numbers that can be represented in a
* double or a 64 bit (long long) int. All other numbers will
* be passed to the client in string form using the yajl_number
* callback. Furthermore, if yajl_number is not NULL, it will
* always be used to return numbers, that is yajl_integer and
* yajl_double will be ignored. If yajl_number is NULL but one
* of yajl_integer or yajl_double are defined, parsing of a
* be passed to the client in string form using the yajl_number()
* callback. Furthermore, if yajl_number() is not NULL, it will
* always be used to return numbers, that is yajl_integer() and
* yajl_double() will be ignored. If yajl_number() is NULL but one
* of yajl_integer() or yajl_double() are defined, parsing of a
* number larger than is representable in a double or 64 bit
* integer will result in a parse error.
* }
*/
typedef struct {
int (* yajl_null)(void * ctx);
@@ -79,7 +78,7 @@ extern "C" {
int (* yajl_number)(void * ctx, const char * numberVal,
size_t numberLen);
/** strings are returned as pointers into the JSON text when,
/** Strings are returned as pointers into the JSON text when,
* possible, as a result, they are _not_ null padded */
int (* yajl_string)(void * ctx, const unsigned char * stringVal,
size_t stringLen);
@@ -93,8 +92,8 @@ extern "C" {
int (* yajl_end_array)(void * ctx);
} yajl_callbacks;
/** allocate a parser handle
* \param callbacks a yajl callbacks structure specifying the
/** Allocate a parser handle
* \param callbacks A yajl callbacks structure specifying the
* functions to call when different JSON entities
* are encountered in the input text. May be NULL,
* which is only useful for validation.
@@ -107,7 +106,7 @@ extern "C" {
void * ctx);
/** configuration parameters for the parser, these may be passed to
/** Configuration parameters for the parser, these may be passed to
* yajl_config() along with option specific argument(s). In general,
* all configuration parameters default to *off*. */
typedef enum {
@@ -115,8 +114,9 @@ extern "C" {
* JSON input. Non-standard, but rather fun
* arguments: toggled off with integer zero, on otherwise.
*
* example:
* Example: \code{.cpp}
* yajl_config(h, yajl_allow_comments, 1); // turn comment support on
* \endcode
*/
yajl_allow_comments = 0x01,
/**
@@ -125,8 +125,9 @@ extern "C" {
* this option makes parsing slightly more expensive (~7% depending
* on processor and compiler in use)
*
* example:
* Example: \code{.cpp}
* yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking
* \endcode
*/
yajl_dont_validate_strings = 0x02,
/**
@@ -157,17 +158,17 @@ extern "C" {
yajl_allow_partial_values = 0x10
} yajl_option;
/** allow the modification of parser options subsequent to handle
* allocation (via yajl_alloc)
/** Allow the modification of parser options subsequent to handle
* allocation (via yajl_alloc())
* \returns zero in case of errors, non-zero otherwise
*/
YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...);
/** free a parser handle */
/** Free a parser handle */
YAJL_API void yajl_free(yajl_handle handle);
/** Parse some json!
* \param hand - a handle to the json parser allocated with yajl_alloc
* \param hand - a handle to the json parser allocated with yajl_alloc()
* \param jsonText - a pointer to the UTF8 json text to be parsed
* \param jsonTextLength - the length, in bytes, of input text
*/
@@ -182,11 +183,11 @@ extern "C" {
* yajl can't know whether another digit is next or some character
* that would terminate the integer token.
*
* \param hand - a handle to the json parser allocated with yajl_alloc
* \param hand - a handle to the json parser allocated with yajl_alloc()
*/
YAJL_API yajl_status yajl_complete_parse(yajl_handle hand);
/** get an error string describing the state of the
/** Get an error string describing the state of the
* parse.
*
* If verbose is non-zero, the message will include the JSON
@@ -194,14 +195,14 @@ extern "C" {
* the specific char.
*
* \returns A dynamically allocated string will be returned which should
* be freed with yajl_free_error
* be freed with yajl_free_error()
*/
YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose,
const unsigned char * jsonText,
size_t jsonTextLength);
/**
* get the amount of data consumed from the last chunk passed to YAJL.
* Get the amount of data consumed from the last chunk passed to YAJL.
*
* In the case of a successful parse this can help you understand if
* the entire buffer was consumed (which will allow you to handle
@@ -214,7 +215,7 @@ extern "C" {
*/
YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand);
/** free an error returned from yajl_get_error */
/** Free an error returned from yajl_get_error() */
YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str);
#ifdef __cplusplus