Merged changes from 3.15 branch, to revno 12807
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* RTEMS startup task for EPICS
|
||||
@@ -287,27 +287,27 @@ initialize_remote_filesystem(char **argv, int hasLocalFilesystem)
|
||||
mount_point[l] = '\0';
|
||||
argv[1] = rtems_bsdnet_bootp_cmdline;
|
||||
/*
|
||||
* Its probably common to embed the mount point in the server
|
||||
* Its probably common to embed the mount point in the server
|
||||
* name so, when this is occurring, dont clobber the mount point
|
||||
* by appending the first node from the command path. This allows
|
||||
* the mount point to be a different path then the server's mount
|
||||
* the mount point to be a different path then the server's mount
|
||||
* path.
|
||||
*
|
||||
* This allows for example a line similar to as follows the DHCP
|
||||
* This allows for example a line similar to as follows the DHCP
|
||||
* configuration file.
|
||||
*
|
||||
* server-name "159.233@192.168.0.123:/vol/vol0/bootRTEMS";
|
||||
*/
|
||||
if ( server_name ) {
|
||||
const size_t allocSize = strlen ( server_name ) + 2;
|
||||
char * const pServerName = mustMalloc( allocSize,
|
||||
char * const pServerName = mustMalloc( allocSize,
|
||||
"NFS mount paths");
|
||||
char * const pServerPath = mustMalloc ( allocSize,
|
||||
char * const pServerPath = mustMalloc ( allocSize,
|
||||
"NFS mount paths");
|
||||
const int scanfStatus = sscanf (
|
||||
server_name,
|
||||
"%[^:] : / %s",
|
||||
pServerName,
|
||||
const int scanfStatus = sscanf (
|
||||
server_name,
|
||||
"%[^:] : / %s",
|
||||
pServerName,
|
||||
pServerPath + 1u );
|
||||
if ( scanfStatus == 2 ) {
|
||||
pServerPath[0u]= '/';
|
||||
@@ -535,7 +535,7 @@ exitHandler(void)
|
||||
rtems_task
|
||||
Init (rtems_task_argument ignored)
|
||||
{
|
||||
int i;
|
||||
int result;
|
||||
char *argv[3] = { NULL, NULL, NULL };
|
||||
char *cp;
|
||||
rtems_task_priority newpri;
|
||||
@@ -661,8 +661,8 @@ Init (rtems_task_argument ignored)
|
||||
atexit(exitHandler);
|
||||
errlogFlush();
|
||||
printf ("***** Starting EPICS application *****\n");
|
||||
i = main ((sizeof argv / sizeof argv[0]) - 1, argv);
|
||||
result = main ((sizeof argv / sizeof argv[0]) - 1, argv);
|
||||
printf ("***** IOC application terminating *****\n");
|
||||
epicsThreadSleep(1.0);
|
||||
epicsExit(0);
|
||||
epicsExit(result);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ INP{link} {
|
||||
\n { line_num ++;}
|
||||
|
||||
. {
|
||||
char message[20];
|
||||
char message[40];
|
||||
YY_BUFFER_STATE *dummy=0;
|
||||
|
||||
sprintf(message,"invalid character '%c'",yytext[0]);
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
SRC_DIRS += $(LIBCOM)/ellLib
|
||||
INC += ellLib.h
|
||||
Com_SRCS += ellLib.c
|
||||
Com_SRCS += ellSort.c
|
||||
|
||||
@@ -56,6 +56,8 @@ epicsShareFunc void ellInsert (ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode);
|
||||
epicsShareFunc ELLNODE * ellNth (ELLLIST *pList, int nodeNum);
|
||||
epicsShareFunc ELLNODE * ellNStep (ELLNODE *pNode, int nStep);
|
||||
epicsShareFunc int ellFind (ELLLIST *pList, ELLNODE *pNode);
|
||||
typedef int (*pListCmp)(const ELLNODE* A, const ELLNODE* B);
|
||||
epicsShareFunc void ellSortStable(ELLLIST *pList, pListCmp);
|
||||
epicsShareFunc void ellFree2 (ELLLIST *pList, FREEFUNC freeFunc);
|
||||
epicsShareFunc void ellVerify (ELLLIST *pList);
|
||||
|
||||
|
||||
83
src/libCom/ellLib/ellSort.c
Normal file
83
src/libCom/ellLib/ellSort.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2014 Brookhaven Science Assoc., as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2016 Michael Davidsaver
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Use of mergesort algorithm based on analysis by
|
||||
* http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsAssert.h"
|
||||
#include "ellLib.h"
|
||||
|
||||
static void ellMoveN(ELLLIST* pTo, ELLLIST* pFrom, int count )
|
||||
{
|
||||
for(;count && ellCount(pFrom); count--) {
|
||||
ELLNODE *node = ellGet(pFrom);
|
||||
ellAdd(pTo, node);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stable (MergeSort) to given list.
|
||||
* The comparison function cmp(A,B) is expected
|
||||
* to return -1 for A<B, 0 for A==B, and 1 for A>B.
|
||||
*/
|
||||
void ellSortStable(ELLLIST *pList, pListCmp cmp)
|
||||
{
|
||||
ELLLIST INP, P, Q;
|
||||
size_t insize = 1; /* initial sub-list size */
|
||||
if(ellCount(pList)<=1)
|
||||
return;
|
||||
|
||||
ellInit(&INP);
|
||||
ellInit(&P);
|
||||
ellInit(&Q);
|
||||
|
||||
/* Process is to iteratively sort
|
||||
* a sequence of sub-lists of size 'insize'
|
||||
*/
|
||||
|
||||
while(insize < ellCount(pList)) {
|
||||
|
||||
assert(ellCount(&INP)==0);
|
||||
|
||||
/* shift previous results to inputs */
|
||||
ellConcat(&INP, pList);
|
||||
|
||||
while(ellCount(&INP))
|
||||
{
|
||||
ELLNODE *p, *q;
|
||||
|
||||
/* Pull out the next pair of sub-lists */
|
||||
ellMoveN(&Q, &INP, insize);
|
||||
ellMoveN(&P, &INP, insize);
|
||||
|
||||
/* merge these sub-lists */
|
||||
while((p=ellFirst(&P)) && (q=ellFirst(&Q)))
|
||||
{
|
||||
if((*cmp)(p,q) < 0) {
|
||||
ellAdd(pList, ellGet(&P));
|
||||
} else {
|
||||
ellAdd(pList, ellGet(&Q));
|
||||
}
|
||||
}
|
||||
|
||||
/* concatenate any remaining to result */
|
||||
if(ellFirst(&P))
|
||||
ellConcat(pList, &P);
|
||||
else if(ellFirst(&Q))
|
||||
ellConcat(pList, &Q);
|
||||
|
||||
assert(!ellFirst(&P) && !ellFirst(&Q));
|
||||
}
|
||||
|
||||
insize *= 2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -559,6 +559,7 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
|
||||
|
||||
if (macros) {
|
||||
if (macParseDefns(NULL, macros, &defines) < 0) {
|
||||
free(redirects);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -571,6 +572,7 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
|
||||
if (handle == NULL) {
|
||||
if (macCreateHandle(&handle, pairs)) {
|
||||
errlogMessage("iocsh: macCreateHandle failed.");
|
||||
free(redirects);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,131 +84,132 @@ static int sighupPipe[2];
|
||||
|
||||
/*
|
||||
*
|
||||
* main()
|
||||
* main()
|
||||
*
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
struct sockaddr_in serverAddr; /* server's address */
|
||||
struct timeval timeout;
|
||||
int status;
|
||||
struct ioc_log_server *pserver;
|
||||
struct sockaddr_in serverAddr; /* server's address */
|
||||
struct timeval timeout;
|
||||
int status;
|
||||
struct ioc_log_server *pserver;
|
||||
|
||||
osiSockIoctl_t optval;
|
||||
osiSockIoctl_t optval;
|
||||
|
||||
status = getConfig();
|
||||
if(status<0){
|
||||
fprintf(stderr, "iocLogServer: EPICS environment underspecified\n");
|
||||
fprintf(stderr, "iocLogServer: failed to initialize\n");
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
status = getConfig();
|
||||
if (status<0) {
|
||||
fprintf(stderr, "iocLogServer: EPICS environment underspecified\n");
|
||||
fprintf(stderr, "iocLogServer: failed to initialize\n");
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
pserver = (struct ioc_log_server *)
|
||||
calloc(1, sizeof *pserver);
|
||||
if(!pserver){
|
||||
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
pserver = (struct ioc_log_server *)
|
||||
calloc(1, sizeof *pserver);
|
||||
if (!pserver) {
|
||||
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
pserver->pfdctx = (void *) fdmgr_init();
|
||||
if(!pserver->pfdctx){
|
||||
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
pserver->pfdctx = (void *) fdmgr_init();
|
||||
if (!pserver->pfdctx) {
|
||||
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the socket. Use ARPA Internet address format and stream
|
||||
* sockets. Format described in <sys/socket.h>.
|
||||
*/
|
||||
pserver->sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
|
||||
if (pserver->sock==INVALID_SOCKET) {
|
||||
/*
|
||||
* Open the socket. Use ARPA Internet address format and stream
|
||||
* sockets. Format described in <sys/socket.h>.
|
||||
*/
|
||||
pserver->sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
|
||||
if (pserver->sock == INVALID_SOCKET) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf(stderr, "iocLogServer: sock create err: %s\n", sockErrBuf);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
fprintf(stderr, "iocLogServer: sock create err: %s\n", sockErrBuf);
|
||||
free(pserver);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
epicsSocketEnableAddressReuseDuringTimeWaitState ( pserver->sock );
|
||||
|
||||
/* Zero the sock_addr structure */
|
||||
memset((void *)&serverAddr, 0, sizeof serverAddr);
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(ioc_log_port);
|
||||
/* Zero the sock_addr structure */
|
||||
memset((void *)&serverAddr, 0, sizeof serverAddr);
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(ioc_log_port);
|
||||
|
||||
/* get server's Internet address */
|
||||
status = bind ( pserver->sock,
|
||||
(struct sockaddr *)&serverAddr,
|
||||
sizeof (serverAddr) );
|
||||
if (status<0) {
|
||||
/* get server's Internet address */
|
||||
status = bind ( pserver->sock,
|
||||
(struct sockaddr *)&serverAddr,
|
||||
sizeof (serverAddr) );
|
||||
if (status < 0) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf(stderr, "iocLogServer: bind err: %s\n", sockErrBuf );
|
||||
fprintf (stderr,
|
||||
"iocLogServer: a server is already installed on port %u?\n",
|
||||
(unsigned)ioc_log_port);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
fprintf(stderr, "iocLogServer: bind err: %s\n", sockErrBuf );
|
||||
fprintf (stderr,
|
||||
"iocLogServer: a server is already installed on port %u?\n",
|
||||
(unsigned)ioc_log_port);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
/* listen and accept new connections */
|
||||
status = listen(pserver->sock, 10);
|
||||
if (status<0) {
|
||||
/* listen and accept new connections */
|
||||
status = listen(pserver->sock, 10);
|
||||
if (status < 0) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf(stderr, "iocLogServer: listen err %s\n", sockErrBuf);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
fprintf(stderr, "iocLogServer: listen err %s\n", sockErrBuf);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
optval = TRUE;
|
||||
status = socket_ioctl(
|
||||
pserver->sock,
|
||||
FIONBIO,
|
||||
&optval);
|
||||
if(status<0){
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
optval = TRUE;
|
||||
status = socket_ioctl(
|
||||
pserver->sock,
|
||||
FIONBIO,
|
||||
&optval);
|
||||
if (status < 0){
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf(stderr, "iocLogServer: ioctl FIONBIO err %s\n", sockErrBuf);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
fprintf(stderr, "iocLogServer: ioctl FIONBIO err %s\n", sockErrBuf);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
# ifdef UNIX
|
||||
status = setupSIGHUP(pserver);
|
||||
if (status<0) {
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
# endif
|
||||
# ifdef UNIX
|
||||
status = setupSIGHUP(pserver);
|
||||
if (status < 0) {
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
# endif
|
||||
|
||||
status = openLogFile(pserver);
|
||||
if (status<0) {
|
||||
fprintf(stderr,
|
||||
"File access problems to `%s' because `%s'\n",
|
||||
ioc_log_file_name,
|
||||
strerror(errno));
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
status = openLogFile(pserver);
|
||||
if (status < 0) {
|
||||
fprintf(stderr,
|
||||
"File access problems to `%s' because `%s'\n",
|
||||
ioc_log_file_name,
|
||||
strerror(errno));
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
status = fdmgr_add_callback(
|
||||
pserver->pfdctx,
|
||||
pserver->sock,
|
||||
fdi_read,
|
||||
acceptNewClient,
|
||||
pserver);
|
||||
if(status<0){
|
||||
fprintf(stderr,
|
||||
"iocLogServer: failed to add read callback\n");
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
status = fdmgr_add_callback(
|
||||
pserver->pfdctx,
|
||||
pserver->sock,
|
||||
fdi_read,
|
||||
acceptNewClient,
|
||||
pserver);
|
||||
if (status < 0) {
|
||||
fprintf(stderr,
|
||||
"iocLogServer: failed to add read callback\n");
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
while(TRUE){
|
||||
timeout.tv_sec = 60; /* 1 min */
|
||||
timeout.tv_usec = 0;
|
||||
fdmgr_pend_event(pserver->pfdctx, &timeout);
|
||||
fflush(pserver->poutfile);
|
||||
}
|
||||
while (TRUE) {
|
||||
timeout.tv_sec = 60; /* 1 min */
|
||||
timeout.tv_usec = 0;
|
||||
fdmgr_pend_event(pserver->pfdctx, &timeout);
|
||||
fflush(pserver->poutfile);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -964,6 +965,7 @@ static int getDirectory(void)
|
||||
"Problem reading o/p from `%s' because `%s'\n",
|
||||
ioc_log_file_command,
|
||||
strerror(errno));
|
||||
(void) pclose(pipe);
|
||||
return IOCLS_ERROR;
|
||||
}
|
||||
(void) pclose(pipe);
|
||||
|
||||
@@ -256,6 +256,18 @@ int epicsStrPrintEscaped(FILE *fp, const char *s, size_t len)
|
||||
return nout;
|
||||
}
|
||||
|
||||
/* Until Base requires POSIX 2008 we must provide our own implementation */
|
||||
size_t epicsStrnLen(const char *s, size_t maxlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i=0; i<maxlen; i++) {
|
||||
if(s[i]=='\0')
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int epicsStrGlobMatch(const char *str, const char *pattern)
|
||||
{
|
||||
const char *cp = NULL, *mp = NULL;
|
||||
|
||||
@@ -33,6 +33,7 @@ epicsShareFunc int epicsStrnCaseCmp(const char *s1, const char *s2, size_t len);
|
||||
epicsShareFunc char * epicsStrDup(const char *s);
|
||||
epicsShareFunc int epicsStrPrintEscaped(FILE *fp, const char *s, size_t n);
|
||||
#define epicsStrSnPrintEscaped epicsStrnEscapedFromRaw
|
||||
epicsShareFunc size_t epicsStrnLen(const char *s, size_t maxlen);
|
||||
epicsShareFunc int epicsStrGlobMatch(const char *str, const char *pattern);
|
||||
epicsShareFunc char * epicsStrtok_r(char *s, const char *delim, char **lasts);
|
||||
epicsShareFunc unsigned int epicsStrHash(const char *str, unsigned int seed);
|
||||
|
||||
@@ -380,7 +380,7 @@ static gtProvider * findProvider(ELLLIST *plist, epicsMutexId lock,
|
||||
|
||||
for (ptp = (gtProvider *)ellFirst(plist);
|
||||
ptp; ptp = (gtProvider *)ellNext(&ptp->node)) {
|
||||
if (ptp->priority == ptp->priority &&
|
||||
if (ptp->priority == priority &&
|
||||
!strcmp(ptp->name, name))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
|
||||
* 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.cpp */
|
||||
/* Author Jeffrey O. Hill */
|
||||
|
||||
// Notes:
|
||||
// 1) The epicsTime::nSec field is not public and so it could be
|
||||
// changed to work more like the fractional seconds field in the NTP time
|
||||
// stamp. That would significantly improve the precision of epicsTime on
|
||||
// 1) The epicsTime::nSec field is not public and so it could be
|
||||
// changed to work more like the fractional seconds field in the NTP time
|
||||
// stamp. That would significantly improve the precision of epicsTime on
|
||||
// 64 bit architectures.
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <string> // vxWorks 6.0 requires this include
|
||||
#include <string> // vxWorks 6.0 requires this include
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "locationException.h"
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "osiSock.h" /* pull in struct timeval */
|
||||
#include "epicsStdio.h"
|
||||
|
||||
static const char pEpicsTimeVersion[] =
|
||||
static const char pEpicsTimeVersion[] =
|
||||
"@(#) " EPICS_VERSION_STRING ", Common Utilities Library " __DATE__;
|
||||
|
||||
//
|
||||
@@ -60,11 +60,13 @@ static const unsigned long NTP_TIME_AT_EPICS_EPOCH =
|
||||
//
|
||||
// epicsTime (const unsigned long secIn, const unsigned long nSecIn)
|
||||
//
|
||||
inline epicsTime::epicsTime (const unsigned long secIn,
|
||||
const unsigned long nSecIn) :
|
||||
secPastEpoch ( nSecIn / nSecPerSec + secIn ),
|
||||
nSec ( nSecIn % nSecPerSec )
|
||||
inline epicsTime::epicsTime (const unsigned long secIn, const unsigned long nSecIn) :
|
||||
secPastEpoch ( secIn ), nSec ( nSecIn )
|
||||
{
|
||||
if (nSecIn >= nSecPerSec) {
|
||||
this->secPastEpoch += nSecIn / nSecPerSec;
|
||||
this->nSec = nSecIn % nSecPerSec;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -93,7 +95,7 @@ epicsTimeLoadTimeInit::epicsTimeLoadTimeInit ()
|
||||
* the ANSI epoch (1/1/1970 00:00:00UTC)
|
||||
* Convert this offset into time_t units, however this must not be
|
||||
* calculated using local time (i.e. using mktime() or similar), since
|
||||
* in the UK the ANSI Epoch had daylight saving time in effect, and
|
||||
* in the UK the ANSI Epoch had daylight saving time in effect, and
|
||||
* the value calculated would be 3600 seconds wrong.*/
|
||||
this->epicsEpochOffset =
|
||||
(double) POSIX_TIME_AT_EPICS_EPOCH / this->time_tSecPerTick;
|
||||
@@ -103,7 +105,7 @@ epicsTimeLoadTimeInit::epicsTimeLoadTimeInit ()
|
||||
this->epicsEpochOffset >= 0) {
|
||||
// We can use simpler code on Posix-compliant systems
|
||||
this->useDiffTimeOptimization = true;
|
||||
this->epicsEpochOffsetAsAnUnsignedLong =
|
||||
this->epicsEpochOffsetAsAnUnsignedLong =
|
||||
static_cast<unsigned long>(this->epicsEpochOffset);
|
||||
} else {
|
||||
// Forced to use the slower but correct code
|
||||
@@ -113,47 +115,26 @@ epicsTimeLoadTimeInit::epicsTimeLoadTimeInit ()
|
||||
}
|
||||
|
||||
//
|
||||
// epicsTime::addNanoSec ()
|
||||
// private epicsTime::addNanoSec ()
|
||||
//
|
||||
// The nano-second field of several of the the UNIX time stamp formats
|
||||
// field is stored in the C type "long".
|
||||
// Most formats keep the nSec value as an unsigned long, so are +ve.
|
||||
// struct timeval's tv_usec may be -1, but I think that means error,
|
||||
// so this private method never needs to handle -ve offsets.
|
||||
//
|
||||
void epicsTime :: addNanoSec ( long nSecAdj )
|
||||
{
|
||||
//
|
||||
// After optimizing this function we now have a larger code which
|
||||
// uses only unsigned integer, and not floating point, arithmetic.
|
||||
// This change benefits embedded CPU's lacking a floating point
|
||||
// co-processor at the expense of some additional code to maintain.
|
||||
//
|
||||
// We hope that all CPU's we run on provide at least an integer
|
||||
// divide instruction which should enable this implementation
|
||||
// to be more efficient than implementations based on branching;
|
||||
// this is presuming that we will run on pipelined architectures.
|
||||
//
|
||||
// Overflow and underflow is expected; in the future we might
|
||||
// operate close to, the modulo of, the EPICS epic.
|
||||
//
|
||||
// We are depending on the normalize operation in the private
|
||||
// constructor used below.
|
||||
//
|
||||
// joh 11-04-2012
|
||||
//
|
||||
if ( nSecAdj >= 0 ) {
|
||||
const unsigned long nSecPlus =
|
||||
static_cast <unsigned long> ( nSecAdj );
|
||||
const unsigned long nSecPlusAdj = nSecPlus % nSecPerSec;
|
||||
const unsigned long secPlusAdj = nSecPlus / nSecPerSec;
|
||||
*this = epicsTime ( this->secPastEpoch+secPlusAdj,
|
||||
this->nSec+nSecPlusAdj );
|
||||
if (nSecAdj <= 0)
|
||||
return;
|
||||
|
||||
if (static_cast<unsigned long>(nSecAdj) >= nSecPerSec) {
|
||||
this->secPastEpoch += nSecAdj / nSecPerSec;
|
||||
nSecAdj %= nSecPerSec;
|
||||
}
|
||||
else {
|
||||
const unsigned long nSecMinus =
|
||||
static_cast <unsigned long> ( -nSecAdj );
|
||||
const unsigned long nSecMinusAdj = nSecMinus % nSecPerSec;
|
||||
const unsigned long secMinusAdj = nSecMinus / nSecPerSec;
|
||||
*this = epicsTime ( this->secPastEpoch - secMinusAdj - 1u,
|
||||
this->nSec + nSecPerSec - nSecMinusAdj );
|
||||
|
||||
this->nSec += nSecAdj; // Can't overflow
|
||||
if (this->nSec >= nSecPerSec) {
|
||||
this->secPastEpoch++;
|
||||
this->nSec -= nSecPerSec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,11 +147,11 @@ epicsTime::epicsTime ( const time_t_wrapper & ansiTimeTicks )
|
||||
static epicsTimeLoadTimeInit & lti = * new epicsTimeLoadTimeInit ();
|
||||
|
||||
//
|
||||
// try to directly map time_t into an unsigned long integer because this is
|
||||
// try to directly map time_t into an unsigned long integer because this is
|
||||
// faster on systems w/o hardware floating point and a simple integer type time_t.
|
||||
//
|
||||
if ( lti.useDiffTimeOptimization ) {
|
||||
// LONG_MAX is used here and not ULONG_MAX because some systems (linux)
|
||||
// LONG_MAX is used here and not ULONG_MAX because some systems (linux)
|
||||
// still store time_t as a long.
|
||||
if ( ansiTimeTicks.ts > 0 && ansiTimeTicks.ts <= LONG_MAX ) {
|
||||
unsigned long ticks = static_cast < unsigned long > ( ansiTimeTicks.ts );
|
||||
@@ -186,8 +167,8 @@ epicsTime::epicsTime ( const time_t_wrapper & ansiTimeTicks )
|
||||
}
|
||||
|
||||
//
|
||||
// otherwise map time_t, which ANSI C and POSIX define as any arithmetic type,
|
||||
// into type double
|
||||
// otherwise map time_t, which ANSI C and POSIX define as any arithmetic type,
|
||||
// into type double
|
||||
//
|
||||
double sec = ansiTimeTicks.ts * lti.time_tSecPerTick - lti.epicsEpochOffset;
|
||||
|
||||
@@ -209,14 +190,14 @@ epicsTime::epicsTime ( const time_t_wrapper & ansiTimeTicks )
|
||||
this->nSec = static_cast <unsigned long> ( ( sec-this->secPastEpoch ) * nSecPerSec );
|
||||
}
|
||||
|
||||
epicsTime::epicsTime (const epicsTimeStamp &ts)
|
||||
epicsTime::epicsTime (const epicsTimeStamp &ts)
|
||||
{
|
||||
if ( ts.nsec < nSecPerSec ) {
|
||||
this->secPastEpoch = ts.secPastEpoch;
|
||||
this->nSec = ts.nsec;
|
||||
}
|
||||
else {
|
||||
throw std::logic_error (
|
||||
throw std::logic_error (
|
||||
"epicsTimeStamp has overflow in nano-seconds field" );
|
||||
}
|
||||
}
|
||||
@@ -262,7 +243,7 @@ epicsTime::operator time_t_wrapper () const
|
||||
return wrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// map type double into time_t which ansi C defines as some arithmetic type
|
||||
//
|
||||
@@ -317,20 +298,82 @@ epicsTime::operator gm_tm_nano_sec () const
|
||||
//
|
||||
epicsTime::epicsTime (const local_tm_nano_sec &tm)
|
||||
{
|
||||
static const time_t mktimeFailure = static_cast <time_t> (-1);
|
||||
time_t_wrapper ansiTimeTicks;
|
||||
struct tm tmp = tm.ansi_tm;
|
||||
time_t_wrapper ansiTimeTicks = { mktime (&tmp) };
|
||||
|
||||
ansiTimeTicks.ts = mktime (&tmp);
|
||||
if (ansiTimeTicks.ts == mktimeFailure) {
|
||||
static const time_t mktimeError = static_cast <time_t> (-1);
|
||||
if (ansiTimeTicks.ts == mktimeError) {
|
||||
throwWithLocation ( formatProblemWithStructTM () );
|
||||
}
|
||||
|
||||
*this = epicsTime (ansiTimeTicks);
|
||||
*this = epicsTime(ansiTimeTicks);
|
||||
this->addNanoSec(tm.nSec);
|
||||
}
|
||||
|
||||
unsigned long nSecAdj = tm.nSec % nSecPerSec;
|
||||
unsigned long secAdj = tm.nSec / nSecPerSec;
|
||||
*this = epicsTime ( this->secPastEpoch+secAdj, this->nSec+nSecAdj );
|
||||
//
|
||||
// epicsTime (const gm_tm_nano_sec &tm)
|
||||
//
|
||||
|
||||
// do conversion avoiding the timezone mechanism
|
||||
static inline int is_leap(int year)
|
||||
{
|
||||
if (year % 400 == 0)
|
||||
return 1;
|
||||
if (year % 100 == 0)
|
||||
return 0;
|
||||
if (year % 4 == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int days_from_0(int year)
|
||||
{
|
||||
year--;
|
||||
return 365 * year + (year / 400) - (year / 100) + (year / 4);
|
||||
}
|
||||
|
||||
static inline int days_from_1970(int year)
|
||||
{
|
||||
static const int days_from_0_to_1970 = days_from_0(1970);
|
||||
return days_from_0(year) - days_from_0_to_1970;
|
||||
}
|
||||
|
||||
static inline int days_from_1jan(int year, int month, int day)
|
||||
{
|
||||
static const int days[2][12] =
|
||||
{
|
||||
{ 0,31,59,90,120,151,181,212,243,273,304,334},
|
||||
{ 0,31,60,91,121,152,182,213,244,274,305,335}
|
||||
};
|
||||
return days[is_leap(year)][month-1] + day - 1;
|
||||
}
|
||||
|
||||
epicsTime::epicsTime (const gm_tm_nano_sec &tm)
|
||||
{
|
||||
int year = tm.ansi_tm.tm_year + 1900;
|
||||
int month = tm.ansi_tm.tm_mon;
|
||||
if (month > 11) {
|
||||
year += month / 12;
|
||||
month %= 12;
|
||||
} else if (month < 0) {
|
||||
int years_diff = (-month + 11) / 12;
|
||||
year -= years_diff;
|
||||
month += 12 * years_diff;
|
||||
}
|
||||
month++;
|
||||
|
||||
int day = tm.ansi_tm.tm_mday;
|
||||
int day_of_year = days_from_1jan(year, month, day);
|
||||
int days_since_epoch = days_from_1970(year) + day_of_year;
|
||||
|
||||
time_t_wrapper ansiTimeTicks;
|
||||
ansiTimeTicks.ts = ((days_since_epoch
|
||||
* 24 + tm.ansi_tm.tm_hour)
|
||||
* 60 + tm.ansi_tm.tm_min)
|
||||
* 60 + tm.ansi_tm.tm_sec;
|
||||
|
||||
*this = epicsTime(ansiTimeTicks);
|
||||
this->addNanoSec(tm.nSec);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -372,9 +415,9 @@ epicsTime::operator struct timeval () const
|
||||
// a direct assignment. On other systems I dont know that we can
|
||||
// guarantee that time_t and timeval :: tv_sec will have the
|
||||
// same epoch or have the same scaling factor to discrete seconds.
|
||||
// For example, on windows time_t changed recently to a 64 bit
|
||||
// For example, on windows time_t changed recently to a 64 bit
|
||||
// quantity but timeval is still a long. That can cause problems
|
||||
// on 32 bit systems. So technically, we should have an os
|
||||
// on 32 bit systems. So technically, we should have an os
|
||||
// dependent conversion between time_t and timeval :: tv_sec?
|
||||
ts.tv_sec = ansiTimeTicks.ts;
|
||||
ts.tv_usec = static_cast < long > ( this->nSec / nSecPerUSec );
|
||||
@@ -391,9 +434,9 @@ epicsTime::epicsTime (const struct timeval &ts)
|
||||
// a direct assignment. On other systems I dont know that we can
|
||||
// guarantee that time_t and timeval :: tv_sec will have the
|
||||
// same epoch or have the same scaling factor to discrete seconds.
|
||||
// For example, on windows time_t changed recently to a 64 bit
|
||||
// For example, on windows time_t changed recently to a 64 bit
|
||||
// quantity but timeval is still a long. That can cause problems
|
||||
// on 32 bit systems. So technically, we should have an os
|
||||
// on 32 bit systems. So technically, we should have an os
|
||||
// dependent conversion between time_t and timeval :: tv_sec?
|
||||
ansiTimeTicks.ts = ts.tv_sec;
|
||||
*this = epicsTime (ansiTimeTicks);
|
||||
@@ -415,7 +458,7 @@ epicsTime::operator l_fp () const
|
||||
{
|
||||
l_fp ts;
|
||||
ts.l_ui = this->secPastEpoch + NTP_TIME_AT_EPICS_EPOCH;
|
||||
ts.l_uf = static_cast < unsigned long >
|
||||
ts.l_uf = static_cast < unsigned long >
|
||||
( ( this->nSec * NTP_FRACTION_DENOMINATOR ) / nSecPerSec );
|
||||
return ts;
|
||||
}
|
||||
@@ -426,14 +469,14 @@ epicsTime::operator l_fp () const
|
||||
epicsTime::epicsTime ( const l_fp & ts )
|
||||
{
|
||||
this->secPastEpoch = ts.l_ui - NTP_TIME_AT_EPICS_EPOCH;
|
||||
this->nSec = static_cast < unsigned long >
|
||||
this->nSec = static_cast < unsigned long >
|
||||
( ( ts.l_uf / NTP_FRACTION_DENOMINATOR ) * nSecPerSec );
|
||||
}
|
||||
|
||||
epicsTime::operator epicsTimeStamp () const
|
||||
{
|
||||
if ( this->nSec >= nSecPerSec ) {
|
||||
throw std::logic_error (
|
||||
throw std::logic_error (
|
||||
"epicsTimeStamp has overflow in nano-seconds field?" );
|
||||
}
|
||||
epicsTimeStamp ts;
|
||||
@@ -444,7 +487,7 @@ epicsTime::operator epicsTimeStamp () const
|
||||
// on 64 bit hosts than the original epicsTimeStamp::secPastEpoch. The
|
||||
// epicsTimeStamp::secPastEpoch is based on epicsUInt32 so that it will
|
||||
// match the original network protocol. Of course one can anticipate
|
||||
// that eventually, a epicsUInt64 based network time stamp will be
|
||||
// that eventually, a epicsUInt64 based network time stamp will be
|
||||
// introduced when 64 bit architectures are more ubiquitous.
|
||||
//
|
||||
// Truncation usually works fine here because the routines in this code
|
||||
@@ -458,14 +501,14 @@ epicsTime::operator epicsTimeStamp () const
|
||||
return ts;
|
||||
}
|
||||
|
||||
// Break up a format string into "<strftime prefix>%0<nnn>f<postfix>"
|
||||
// (where <nnn> in an unsigned integer)
|
||||
// Break up a format string into "<strftime prefix>%0<nnn>f<postfix>"
|
||||
// (where <nnn> in an unsigned integer)
|
||||
// Result:
|
||||
// A) Copies a prefix which is valid for ANSI strftime into the supplied
|
||||
// buffer setting the buffer to an empty string if no prefix is present.
|
||||
// B) Indicates whether a valid "%0<n>f]" is present or not and if so
|
||||
// B) Indicates whether a valid "%0<n>f]" is present or not and if so
|
||||
// specifying its nnnn
|
||||
// C) returning a pointer to the postfix (which might be passed again
|
||||
// C) returning a pointer to the postfix (which might be passed again
|
||||
// to fracFormatFind.
|
||||
static const char * fracFormatFind (
|
||||
const char * const pFormat,
|
||||
@@ -529,8 +572,8 @@ static const char * fracFormatFind (
|
||||
//
|
||||
// size_t epicsTime::strftime ()
|
||||
//
|
||||
size_t epicsTime::strftime (
|
||||
char * pBuff, size_t bufLength, const char * pFormat ) const
|
||||
size_t epicsTime::strftime (
|
||||
char * pBuff, size_t bufLength, const char * pFormat ) const
|
||||
{
|
||||
if ( bufLength == 0u ) {
|
||||
return 0u;
|
||||
@@ -547,15 +590,15 @@ size_t epicsTime::strftime (
|
||||
const char * pFmt = pFormat;
|
||||
size_t bufLenLeft = bufLength;
|
||||
while ( *pFmt != '\0' && bufLenLeft > 1 ) {
|
||||
// look for "%0<n>f" at the end (used for fractional second formatting)
|
||||
// look for "%0<n>f" at the end (used for fractional second formatting)
|
||||
char strftimePrefixBuf [256];
|
||||
bool fracFmtFound;
|
||||
unsigned long fracWid = 0;
|
||||
pFmt = fracFormatFind (
|
||||
pFmt,
|
||||
pFmt,
|
||||
strftimePrefixBuf, sizeof ( strftimePrefixBuf ),
|
||||
fracFmtFound, fracWid );
|
||||
|
||||
|
||||
// nothing more in the string, then quit
|
||||
if ( ! ( strftimePrefixBuf[0] != '\0' || fracFmtFound ) ) {
|
||||
break;
|
||||
@@ -657,7 +700,7 @@ void epicsTime::show ( unsigned level ) const
|
||||
if ( level > 1 ) {
|
||||
// this also suppresses the "defined, but not used"
|
||||
// warning message
|
||||
printf ( "epicsTime: revision \"%s\"\n",
|
||||
printf ( "epicsTime: revision \"%s\"\n",
|
||||
pEpicsTimeVersion );
|
||||
}
|
||||
|
||||
@@ -704,10 +747,10 @@ epicsTime epicsTime::operator + (const double &rhs) const
|
||||
}
|
||||
|
||||
//
|
||||
// operator -
|
||||
// operator -
|
||||
//
|
||||
// To make this code robust during timestamp rollover events
|
||||
// time stamp differences greater than one half full scale are
|
||||
// time stamp differences greater than one half full scale are
|
||||
// interpreted as rollover situations:
|
||||
//
|
||||
// when RHS is greater than THIS:
|
||||
@@ -729,7 +772,7 @@ double epicsTime::operator - (const epicsTime &rhs) const
|
||||
// so the unsigned to signed conversion is ok
|
||||
//
|
||||
if (this->nSec>=rhs.nSec) {
|
||||
nSecRes = this->nSec - rhs.nSec;
|
||||
nSecRes = this->nSec - rhs.nSec;
|
||||
}
|
||||
else {
|
||||
nSecRes = rhs.nSec - this->nSec;
|
||||
@@ -746,7 +789,7 @@ double epicsTime::operator - (const epicsTime &rhs) const
|
||||
if (secRes > ULONG_MAX/2) {
|
||||
//
|
||||
// In this situation where the difference is more than
|
||||
// 68 years assume that the seconds counter has rolled
|
||||
// 68 years assume that the seconds counter has rolled
|
||||
// over and compute the "wrap around" difference
|
||||
//
|
||||
secRes = 1 + (ULONG_MAX-secRes);
|
||||
@@ -761,7 +804,7 @@ double epicsTime::operator - (const epicsTime &rhs) const
|
||||
if (secRes > ULONG_MAX/2) {
|
||||
//
|
||||
// In this situation where the difference is more than
|
||||
// 68 years assume that the seconds counter has rolled
|
||||
// 68 years assume that the seconds counter has rolled
|
||||
// over and compute the "wrap around" difference
|
||||
//
|
||||
secRes = 1 + (ULONG_MAX-secRes);
|
||||
@@ -770,7 +813,7 @@ double epicsTime::operator - (const epicsTime &rhs) const
|
||||
}
|
||||
}
|
||||
|
||||
return secRes + nSecRes/nSecPerSec;
|
||||
return secRes + nSecRes/nSecPerSec;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -791,7 +834,7 @@ bool epicsTime::operator <= (const epicsTime &rhs) const
|
||||
else {
|
||||
//
|
||||
// In this situation where the difference is more than
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// over and compute the "wrap around" result
|
||||
//
|
||||
rc = false;
|
||||
@@ -808,7 +851,7 @@ bool epicsTime::operator <= (const epicsTime &rhs) const
|
||||
else {
|
||||
//
|
||||
// In this situation where the difference is more than
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// over and compute the "wrap around" result
|
||||
//
|
||||
rc = true;
|
||||
@@ -843,7 +886,7 @@ bool epicsTime::operator < (const epicsTime &rhs) const
|
||||
else {
|
||||
//
|
||||
// In this situation where the difference is more than
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// over and compute the "wrap around" result
|
||||
//
|
||||
rc = false;
|
||||
@@ -860,7 +903,7 @@ bool epicsTime::operator < (const epicsTime &rhs) const
|
||||
else {
|
||||
//
|
||||
// In this situation where the difference is more than
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// 69 years assume that the seconds counter has rolled
|
||||
// over and compute the "wrap around" result
|
||||
//
|
||||
rc = true;
|
||||
@@ -881,7 +924,7 @@ extern "C" {
|
||||
//
|
||||
// ANSI C interface
|
||||
//
|
||||
// its too bad that these cant be implemented with inline functions
|
||||
// its too bad that these cant be implemented with inline functions
|
||||
// at least when running the GNU compiler
|
||||
//
|
||||
epicsShareFunc int epicsShareAPI epicsTimeToTime_t (time_t *pDest, const epicsTimeStamp *pSrc)
|
||||
@@ -944,6 +987,19 @@ extern "C" {
|
||||
}
|
||||
return epicsTimeOK;
|
||||
}
|
||||
epicsShareFunc int epicsShareAPI epicsTimeFromGMTM (epicsTimeStamp *pDest, const struct tm *pSrc, unsigned long nSecSrc)
|
||||
{
|
||||
try {
|
||||
gm_tm_nano_sec tmns;
|
||||
tmns.ansi_tm = *pSrc;
|
||||
tmns.nSec = nSecSrc;
|
||||
*pDest = epicsTime (tmns);
|
||||
}
|
||||
catch (...) {
|
||||
return S_time_conversion;
|
||||
}
|
||||
return epicsTimeOK;
|
||||
}
|
||||
epicsShareFunc int epicsShareAPI epicsTimeToTimespec (struct timespec *pDest, const epicsTimeStamp *pSrc)
|
||||
{
|
||||
try {
|
||||
@@ -1075,4 +1131,3 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,10 +106,12 @@ public:
|
||||
epicsTime & operator = ( const local_tm_nano_sec & );
|
||||
|
||||
/*
|
||||
* convert to ANSI Cs "struct tm" (with nano seconds)
|
||||
* convert to and from ANSI Cs "struct tm" (with nano seconds)
|
||||
* adjusted for GM time (UTC)
|
||||
*/
|
||||
operator gm_tm_nano_sec () const;
|
||||
epicsTime ( const gm_tm_nano_sec & );
|
||||
epicsTime & operator = ( const gm_tm_nano_sec & );
|
||||
|
||||
/* convert to and from POSIX RTs "struct timespec" */
|
||||
operator struct timespec () const;
|
||||
@@ -201,13 +203,15 @@ epicsShareFunc int epicsShareAPI epicsTimeToTime_t (
|
||||
epicsShareFunc int epicsShareAPI epicsTimeFromTime_t (
|
||||
epicsTimeStamp * pDest, time_t src );
|
||||
|
||||
/*convert to and from ANSI C's "struct tm" with nano seconds */
|
||||
/* convert to and from ANSI C's "struct tm" with nano seconds */
|
||||
epicsShareFunc int epicsShareAPI epicsTimeToTM (
|
||||
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
|
||||
epicsShareFunc int epicsShareAPI epicsTimeToGMTM (
|
||||
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
|
||||
epicsShareFunc int epicsShareAPI epicsTimeFromTM (
|
||||
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
|
||||
epicsShareFunc int epicsShareAPI epicsTimeFromGMTM (
|
||||
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
|
||||
|
||||
/* convert to and from POSIX RT's "struct timespec" */
|
||||
epicsShareFunc int epicsShareAPI epicsTimeToTimespec (
|
||||
@@ -319,6 +323,11 @@ inline epicsTime & epicsTime::operator = ( const local_tm_nano_sec & rhs )
|
||||
return *this = epicsTime ( rhs );
|
||||
}
|
||||
|
||||
inline epicsTime & epicsTime::operator = ( const gm_tm_nano_sec & rhs )
|
||||
{
|
||||
return *this = epicsTime ( rhs );
|
||||
}
|
||||
|
||||
inline epicsTime & epicsTime::operator = ( const struct timespec & rhs )
|
||||
{
|
||||
*this = epicsTime ( rhs );
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* 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: Eric Norum
|
||||
@@ -38,6 +38,7 @@ typedef socklen_t osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -42,6 +42,7 @@ typedef socklen_t osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
@@ -72,4 +73,3 @@ typedef socklen_t osiSocklen_t;
|
||||
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ static int receiveMessage(
|
||||
return -1;
|
||||
}
|
||||
rsize = receiveMessage(id, id->localBuf, id->maxSize, wait, delay);
|
||||
if ((rsize < 0) || (rsize > size))
|
||||
if (rsize > size)
|
||||
return -1;
|
||||
memcpy(buffer, id->localBuf, rsize);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* RTEMS osdSock.h
|
||||
@@ -35,7 +35,7 @@ int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, str
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
@@ -49,6 +49,7 @@ typedef socklen_t osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
@@ -75,7 +76,7 @@ typedef socklen_t osiSocklen_t;
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE (0xffffffff)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For shutdown()
|
||||
|
||||
@@ -427,8 +427,6 @@ void epicsThreadGetName (epicsThreadId id, char *name, size_t size)
|
||||
struct taskVar *v;
|
||||
int haveName = 0;
|
||||
|
||||
if (size <= 0)
|
||||
return;
|
||||
taskVarLock ();
|
||||
for (v=taskVarHead ; v != NULL ; v=v->forw) {
|
||||
if (v->id == tid) {
|
||||
@@ -690,6 +688,7 @@ void epicsThreadShow (epicsThreadId id, unsigned int level)
|
||||
for (v = taskVarHead ; v != NULL ; v = v->forw) {
|
||||
if ((rtems_id)id == v->id) {
|
||||
epicsThreadShowInfo (v, level);
|
||||
taskVarUnlock ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef osdSockH
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* winsock2.h changes the structure alignment to 4 if
|
||||
* winsock2.h changes the structure alignment to 4 if
|
||||
* WIN32 isnt set which can be a source of confusion
|
||||
*/
|
||||
#ifndef WIN32
|
||||
@@ -48,6 +48,7 @@ typedef int osiSocklen_t;
|
||||
#define SOCK_ENOBUFS WSAENOBUFS
|
||||
#define SOCK_ECONNRESET WSAECONNRESET
|
||||
#define SOCK_ETIMEDOUT WSAETIMEDOUT
|
||||
#define SOCK_EACCES WSAEACCES
|
||||
#define SOCK_EADDRINUSE WSAEADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL WSAEADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED WSAECONNREFUSED
|
||||
|
||||
@@ -523,13 +523,8 @@ static win32ThreadParam * epicsThreadParmCreate ( const char *pName )
|
||||
|
||||
pParmWIN32 = calloc ( 1, sizeof ( *pParmWIN32 ) + strlen ( pName ) + 1 );
|
||||
if ( pParmWIN32 ) {
|
||||
if ( pName ) {
|
||||
pParmWIN32->pName = (char *) ( pParmWIN32 + 1 );
|
||||
strcpy ( pParmWIN32->pName, pName );
|
||||
}
|
||||
else {
|
||||
pParmWIN32->pName = 0;
|
||||
}
|
||||
pParmWIN32->pName = (char *) ( pParmWIN32 + 1 );
|
||||
strcpy ( pParmWIN32->pName, pName );
|
||||
pParmWIN32->isSuspended = 0;
|
||||
}
|
||||
return pParmWIN32;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* cygwin32 specific include
|
||||
@@ -49,6 +49,7 @@ typedef int osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
@@ -67,4 +68,3 @@ typedef int osiSocklen_t;
|
||||
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef osdSockH
|
||||
@@ -29,7 +29,7 @@
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
@@ -43,6 +43,7 @@ typedef socklen_t osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
@@ -77,4 +78,3 @@ typedef socklen_t osiSocklen_t;
|
||||
#endif
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef socklen_t osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -39,7 +39,7 @@ typedef int osiSockIoctl_t;
|
||||
|
||||
#if SOLARIS > 6 || defined ( _SOCKLEN_T )
|
||||
typedef uint32_t osiSocklen_t;
|
||||
#else
|
||||
#else
|
||||
typedef int osiSocklen_t;
|
||||
#endif
|
||||
|
||||
@@ -51,6 +51,7 @@ typedef int osiSockIoctl_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
@@ -80,9 +81,8 @@ typedef int osiSockIoctl_t;
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE (0xffffffff)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* vxWorks specific socket include
|
||||
@@ -44,7 +44,7 @@ int sysClkRateGet(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
@@ -72,6 +72,7 @@ typedef int osiSocklen_t;
|
||||
#define SOCK_ENOBUFS ENOBUFS
|
||||
#define SOCK_ECONNRESET ECONNRESET
|
||||
#define SOCK_ETIMEDOUT ETIMEDOUT
|
||||
#define SOCK_EACCES EACCES
|
||||
#define SOCK_EADDRINUSE EADDRINUSE
|
||||
#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
|
||||
#define SOCK_ECONNREFUSED ECONNREFUSED
|
||||
@@ -93,7 +94,7 @@ typedef int osiSocklen_t;
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE (0xffffffff)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_SIZEOF_ADDR_IFREQ)
|
||||
# define ifreq_size(pifreq) _SIZEOF_ADDR_IFREQ(*pifreq)
|
||||
@@ -104,5 +105,3 @@ typedef int osiSocklen_t;
|
||||
#endif
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 Michael Davidsaver
|
||||
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
@@ -11,6 +12,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ellLib.h"
|
||||
#include "dbDefs.h"
|
||||
#include "epicsUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
@@ -20,15 +22,13 @@ struct myItem {
|
||||
int num;
|
||||
};
|
||||
|
||||
MAIN(epicsEllTest)
|
||||
static void testList(void)
|
||||
{
|
||||
ELLLIST list1;
|
||||
ELLLIST list2 = ELLLIST_INIT;
|
||||
int i1 = 1;
|
||||
struct myItem *pitem, *pfirst, *pick;
|
||||
|
||||
testPlan(70);
|
||||
|
||||
list1.count = 27;
|
||||
list1.node.next = (ELLNODE *) 0x01010101;
|
||||
list1.node.previous = (ELLNODE *) 0x10101010;
|
||||
@@ -192,6 +192,77 @@ MAIN(epicsEllTest)
|
||||
|
||||
ellFree2(&list1, free);
|
||||
testOk1(ellCount(&list1) == 0);
|
||||
}
|
||||
|
||||
typedef struct { int A, B; } input_t;
|
||||
|
||||
static int myItemCmp(const ELLNODE *a, const ELLNODE *b)
|
||||
{
|
||||
struct myItem *A = CONTAINER(a, struct myItem, node),
|
||||
*B = CONTAINER(b, struct myItem, node);
|
||||
|
||||
if (A->num < B->num) return -1;
|
||||
else if(A->num > B->num) return 1;
|
||||
else if(A->list < B->list) return -1;
|
||||
else if(A->list > B->list) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
static const input_t input[] = {
|
||||
{-4, 0},
|
||||
{-5, 0},
|
||||
{0,0},
|
||||
{50,0},
|
||||
{0,1},
|
||||
{5,0},
|
||||
{5,1}
|
||||
};
|
||||
|
||||
static
|
||||
void testSort(const input_t *inp, size_t ninp)
|
||||
{
|
||||
unsigned i;
|
||||
ELLLIST list = ELLLIST_INIT;
|
||||
struct myItem *alloc = calloc(ninp, sizeof(*alloc));
|
||||
|
||||
if(!alloc) testAbort("testSort allocation fails");
|
||||
|
||||
for(i=0; i<ninp; i++) {
|
||||
struct myItem *it = &alloc[i];
|
||||
|
||||
it->num = inp[i].A;
|
||||
it->list= inp[i].B;
|
||||
|
||||
ellAdd(&list, &it->node);
|
||||
}
|
||||
|
||||
ellSortStable(&list, &myItemCmp);
|
||||
|
||||
testOk(ellCount(&list)==ninp, "output length %u == %u", (unsigned)ellCount(&list), (unsigned)ninp);
|
||||
if(ellCount(&list)==0) {
|
||||
testSkip(ninp-1, "all items lost");
|
||||
}
|
||||
|
||||
{
|
||||
struct myItem *prev = CONTAINER(ellFirst(&list), struct myItem, node),
|
||||
*next;
|
||||
|
||||
for(next = CONTAINER(ellNext(&prev->node), struct myItem, node);
|
||||
next;
|
||||
prev = next, next = CONTAINER(ellNext(&next->node), struct myItem, node))
|
||||
{
|
||||
int cond = (prev->num<next->num) || (prev->num==next->num && prev->list<next->list);
|
||||
testOk(cond, "%d:%d < %d:%d", prev->num, prev->list, next->num, next->list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MAIN(epicsEllTest)
|
||||
{
|
||||
testPlan(77);
|
||||
|
||||
testList();
|
||||
testSort(input, NELEMENTS(input));
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -250,5 +250,12 @@ MAIN(epicsEventTest)
|
||||
eventWaitTest();
|
||||
eventWakeupTest();
|
||||
|
||||
free(name);
|
||||
free(id);
|
||||
epicsRingPointerDelete(pinfo->ring);
|
||||
epicsMutexDestroy(pinfo->lockRing);
|
||||
epicsEventDestroy(event);
|
||||
free(pinfo);
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -279,5 +279,11 @@ MAIN(epicsMutexTest)
|
||||
|
||||
epicsMutexPerformance ();
|
||||
|
||||
free(pinfo);
|
||||
free(arg);
|
||||
free(name);
|
||||
free(id);
|
||||
epicsMutexDestroy(mutex);
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,14 @@ static void testEpicsSnprintf(void) {
|
||||
const char *expected = exbuffer;
|
||||
int size;
|
||||
int rtn, rlen;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if (defined(_MSC_VER) && _MSC_VER < 1900) || \
|
||||
(defined(_MINGW) && defined(_TWO_DIGIT_EXPONENT))
|
||||
_set_output_format(_TWO_DIGIT_EXPONENT);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
sprintf(exbuffer, format, ivalue, fvalue, svalue);
|
||||
rlen = strlen(expected)+1;
|
||||
|
||||
@@ -121,11 +128,7 @@ void testStdoutRedir (const char *report)
|
||||
|
||||
MAIN(epicsStdioTest)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
testPlan(166);
|
||||
#else
|
||||
testPlan(163);
|
||||
#endif
|
||||
testEpicsSnprintf();
|
||||
#ifdef __rtems__
|
||||
/* ensure there is a writeable area */
|
||||
|
||||
@@ -87,7 +87,7 @@ MAIN(epicsStringTest)
|
||||
char *s;
|
||||
int status;
|
||||
|
||||
testPlan(402);
|
||||
testPlan(406);
|
||||
|
||||
testChars();
|
||||
|
||||
@@ -122,6 +122,11 @@ MAIN(epicsStringTest)
|
||||
testOk1(epicsStrHash(abcd, 0) == epicsMemHash(abcde, 4, 0));
|
||||
testOk1(epicsStrHash(abcd, 0) != epicsMemHash("abcd\0", 5, 0));
|
||||
|
||||
testOk1(epicsStrnLen("abcd", 5)==4);
|
||||
testOk1(epicsStrnLen("abcd", 4)==4);
|
||||
testOk1(epicsStrnLen("abcd", 3)==3);
|
||||
testOk1(epicsStrnLen("abcd", 0)==0);
|
||||
|
||||
testGlob();
|
||||
|
||||
memset(result, 'x', sizeof(result));
|
||||
|
||||
@@ -43,7 +43,7 @@ MAIN(epicsTimeTest)
|
||||
const int wasteTime = 100000;
|
||||
const int nTimes = 10;
|
||||
|
||||
testPlan(15 + nTimes * 18);
|
||||
testPlan(15 + nTimes * 19);
|
||||
|
||||
try {
|
||||
const epicsTimeStamp epochTS = {0, 0};
|
||||
@@ -200,6 +200,11 @@ MAIN(epicsTimeTest)
|
||||
epicsTime beginANSI = ansiDate;
|
||||
testOk1(beginANSI + diff == now);
|
||||
|
||||
// test struct gmtm round-trip conversion
|
||||
gm_tm_nano_sec ansiGmDate = begin;
|
||||
epicsTime beginGMANSI = ansiGmDate;
|
||||
testOk1(beginGMANSI + diff == now);
|
||||
|
||||
// test struct timespec round-trip conversion
|
||||
struct timespec ts = begin;
|
||||
epicsTime beginTS = ts;
|
||||
|
||||
@@ -115,5 +115,9 @@ MAIN(ringBytesTest)
|
||||
testOk(n==1, "ring get %d", 1);
|
||||
check(ring, RINGSIZE);
|
||||
|
||||
epicsRingBytesDelete(ring);
|
||||
epicsEventDestroy(consumerEvent);
|
||||
free(pinfo);
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user