From c16c4590ec1e71bc790e54a495b78add7c115b05 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 2 Dec 2014 15:25:09 -0600 Subject: [PATCH 1/2] Replace epicsTimeERROR with specific error status values Introduced error status values for epicsTime routines. The epicsTimeERROR identifier no longer exists, so code that uses it will no longer compile (deliberately). Replace all uses of it with a specific error status value. --- documentation/RELEASE_NOTES.html | 9 +++++++ src/libCom/error/Makefile | 1 + src/libCom/error/errMdef.h | 1 + src/libCom/osi/epicsGeneralTime.c | 40 +++++++++++++++------------- src/libCom/osi/epicsTime.cpp | 22 +++++++-------- src/libCom/osi/epicsTime.h | 11 ++++++-- src/libCom/osi/os/Darwin/osdTime.cpp | 5 ++-- src/libCom/osi/os/RTEMS/osdTime.cpp | 4 +-- src/libCom/osi/os/WIN32/osdTime.cpp | 14 +++++----- src/libCom/osi/os/posix/osdTime.cpp | 7 ++--- src/libCom/osi/osiNTPTime.c | 4 +-- src/std/dev/devGeneralTime.c | 2 +- 12 files changed, 72 insertions(+), 48 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index b2e5fdc65..48dacb281 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -20,6 +20,15 @@ --> +

epicsTime API return status

+ +

The epicsTime routines that used to return epicsTimeERROR now return a specific +S_time_ status value, allowing the caller to discover the reason for any failure. +The identifier epicsTimeERROR is no longer defined, so any references to +it in source code will no longer compile. The identifier epicsTimeOK still exists +and has the value 0 as before, so most code that uses these APIs can be changed in +a way that is backwards-compatible with the previous return status.

+

Callback subsystem API

Added a new macro callbackGetPriority(prio, callback) to the diff --git a/src/libCom/error/Makefile b/src/libCom/error/Makefile index bf81074e8..0a99b0def 100644 --- a/src/libCom/error/Makefile +++ b/src/libCom/error/Makefile @@ -22,6 +22,7 @@ Com_SRCS += errSymTbl.c # For bldErrSymTbl # ERR_S_FILES += $(LIBCOM)/osi/devLib.h +ERR_S_FILES += $(LIBCOM)/osi/epicsTime.h ERR_S_FILES += $(LIBCOM)/as/asLib.h ERR_S_FILES += $(LIBCOM)/misc/epicsStdlib.h ERR_S_FILES += $(LIBCOM)/pool/epicsThreadPool.h diff --git a/src/libCom/error/errMdef.h b/src/libCom/error/errMdef.h index 27b693d8c..e511d912b 100644 --- a/src/libCom/error/errMdef.h +++ b/src/libCom/error/errMdef.h @@ -50,6 +50,7 @@ extern "C" { #define M_gddFuncTbl (526 <<16) /*gdd jump table*/ #define M_stdlib (527 <<16) /*EPICS Standard library*/ #define M_pool (528 <<16) /*Thread pool*/ +#define M_time (529 <<16) /*epicsTime*/ epicsShareFunc void epicsShareAPI errSymLookup(long status, char *pBuf, unsigned bufLength); epicsShareFunc void epicsShareAPI errSymTest(unsigned short modnum, unsigned short begErrNum, unsigned short endErrNum); diff --git a/src/libCom/osi/epicsGeneralTime.c b/src/libCom/osi/epicsGeneralTime.c index 8ef8a73cc..7f8e1b66f 100644 --- a/src/libCom/osi/epicsGeneralTime.c +++ b/src/libCom/osi/epicsGeneralTime.c @@ -86,7 +86,7 @@ void generalTime_Init(void) int generalTimeGetExceptPriority(epicsTimeStamp *pDest, int *pPrio, int ignore) { gtProvider *ptp; - int status = epicsTimeERROR; + int status = S_time_noProvider; generalTime_Init(); @@ -107,6 +107,7 @@ int generalTimeGetExceptPriority(epicsTimeStamp *pDest, int *pPrio, int ignore) *pPrio = ptp->priority; } else { int key; + *pDest = gtPvt.lastProvidedTime; if (pPrio) *pPrio = gtPvt.lastTimeProvider->priority; @@ -117,8 +118,7 @@ int generalTimeGetExceptPriority(epicsTimeStamp *pDest, int *pPrio, int ignore) break; } } - if (status == epicsTimeERROR && - ignore == 0) + if (status && ignore == 0) gtPvt.lastTimeProvider = NULL; epicsMutexUnlock(gtPvt.timeListLock); @@ -135,7 +135,8 @@ int epicsTimeGetCurrentInt(epicsTimeStamp *pDest) gtProvider *ptp = gtPvt.lastTimeProvider; if (ptp == NULL || - ptp->getInt.Time == NULL) return epicsTimeERROR; + ptp->getInt.Time == NULL) + return S_time_noProvider; return ptp->getInt.Time(pDest); } @@ -145,20 +146,20 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, int *pPrio) { gtProvider *ptp; - int status = epicsTimeERROR; + int status = S_time_noProvider; generalTime_Init(); if ((eventNumber < 0 || eventNumber >= NUM_TIME_EVENTS) && (eventNumber != epicsTimeEventBestTime)) - return status; + return S_time_badEvent; epicsMutexMustLock(gtPvt.eventListLock); for (ptp = (gtProvider *)ellFirst(>Pvt.eventProviders); ptp; ptp = (gtProvider *)ellNext(&ptp->node)) { status = ptp->get.Event(pDest, eventNumber); - if (status != epicsTimeERROR) { + if (status == epicsTimeOK) { gtPvt.lastEventProvider = ptp; if (pPrio) *pPrio = ptp->priority; @@ -169,6 +170,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, gtPvt.lastProvidedBestTime = *pDest; } else { int key; + *pDest = gtPvt.lastProvidedBestTime; key = epicsInterruptLock(); gtPvt.ErrorCounts++; @@ -180,6 +182,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, gtPvt.eventTime[eventNumber] = *pDest; } else { int key; + *pDest = gtPvt.eventTime[eventNumber]; key = epicsInterruptLock(); gtPvt.ErrorCounts++; @@ -189,7 +192,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, break; } } - if (status == epicsTimeERROR) + if (status) gtPvt.lastEventProvider = NULL; epicsMutexUnlock(gtPvt.eventListLock); @@ -213,7 +216,8 @@ int epicsTimeGetEventInt(epicsTimeStamp *pDest, int eventNumber) gtProvider *ptp = gtPvt.lastEventProvider; if (ptp == NULL || - ptp->getInt.Event == NULL) return epicsTimeERROR; + ptp->getInt.Event == NULL) + return S_time_noProvider; return ptp->getInt.Event(pDest, eventNumber); } @@ -271,11 +275,11 @@ int generalTimeRegisterEventProvider(const char *name, int priority, generalTime_Init(); if (name == NULL || getEvent == NULL) - return epicsTimeERROR; + return S_time_badArgs; ptp = (gtProvider *)malloc(sizeof(gtProvider)); if (ptp == NULL) - return epicsTimeERROR; + return S_time_noMemory; ptp->name = epicsStrDup(name); ptp->priority = priority; @@ -293,7 +297,7 @@ int generalTimeAddIntEventProvider(const char *name, int priority, gtProvider *ptp = findProvider(>Pvt.eventProviders, gtPvt.eventListLock, name, priority); if (ptp == NULL) - return epicsTimeERROR; + return S_time_noProvider; ptp->getInt.Event = getEvent; @@ -308,11 +312,11 @@ int generalTimeRegisterCurrentProvider(const char *name, int priority, generalTime_Init(); if (name == NULL || getTime == NULL) - return epicsTimeERROR; + return S_time_badArgs; ptp = (gtProvider *)malloc(sizeof(gtProvider)); if (ptp == NULL) - return epicsTimeERROR; + return S_time_noMemory; ptp->name = epicsStrDup(name); ptp->priority = priority; @@ -330,7 +334,7 @@ int generalTimeAddIntCurrentProvider(const char *name, int priority, gtProvider *ptp = findProvider(>Pvt.timeProviders, gtPvt.timeListLock, name, priority); if (ptp == NULL) - return epicsTimeERROR; + return S_time_noProvider; ptp->getInt.Time = getTime; @@ -388,7 +392,7 @@ long generalTimeReport(int level) if (!message) { epicsMutexUnlock(gtPvt.timeListLock); printf("Out of memory\n"); - return epicsTimeERROR; + return S_time_noMemory; } pout = message; @@ -399,7 +403,7 @@ long generalTimeReport(int level) ptp->name, ptp->priority); if (level) { epicsTimeStamp tempTS; - if (ptp->get.Time(&tempTS) != epicsTimeERROR) { + if (ptp->get.Time(&tempTS) == epicsTimeOK) { char tempTSText[40]; epicsTimeToStrftime(tempTSText, sizeof(tempTSText), "%Y-%m-%d %H:%M:%S.%06f", &tempTS); @@ -430,7 +434,7 @@ long generalTimeReport(int level) if (!message) { epicsMutexUnlock(gtPvt.eventListLock); printf("Out of memory\n"); - return epicsTimeERROR; + return S_time_noMemory; } pout = message; diff --git a/src/libCom/osi/epicsTime.cpp b/src/libCom/osi/epicsTime.cpp index b85b67b8e..59514c2f7 100644 --- a/src/libCom/osi/epicsTime.cpp +++ b/src/libCom/osi/epicsTime.cpp @@ -284,7 +284,7 @@ epicsTime::operator local_tm_nano_sec () const local_tm_nano_sec tm; int status = epicsTime_localtime ( &ansiTimeTicks.ts, &tm.ansi_tm ); - if ( status != epicsTimeOK ) { + if ( status ) { throw std::logic_error ( "epicsTime_localtime failed" ); } @@ -303,7 +303,7 @@ epicsTime::operator gm_tm_nano_sec () const gm_tm_nano_sec tm; int status = epicsTime_gmtime ( &ansiTimeTicks.ts, &tm.ansi_tm ); - if ( status != epicsTimeOK ) { + if ( status ) { throw std::logic_error ( "epicsTime_gmtime failed" ); } @@ -891,7 +891,7 @@ extern "C" { *pDest = dst.ts; } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -903,7 +903,7 @@ extern "C" { *pDest = epicsTime ( dst ); } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -915,7 +915,7 @@ extern "C" { *pNSecDest = tmns.nSec; } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -927,7 +927,7 @@ extern "C" { *pNSecDest = gmtmns.nSec; } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -940,7 +940,7 @@ extern "C" { *pDest = epicsTime (tmns); } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -950,7 +950,7 @@ extern "C" { *pDest = epicsTime (*pSrc); } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -960,7 +960,7 @@ extern "C" { *pDest = epicsTime (*pSrc); } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -970,7 +970,7 @@ extern "C" { *pDest = epicsTime (*pSrc); } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } @@ -980,7 +980,7 @@ extern "C" { *pDest = epicsTime (*pSrc); } catch (...) { - return epicsTimeERROR; + return S_time_conversion; } return epicsTimeOK; } diff --git a/src/libCom/osi/epicsTime.h b/src/libCom/osi/epicsTime.h index a36d6afe3..bf8f77c87 100644 --- a/src/libCom/osi/epicsTime.h +++ b/src/libCom/osi/epicsTime.h @@ -17,6 +17,7 @@ #include "shareLib.h" #include "epicsTypes.h" #include "osdTime.h" +#include "errMdef.h" /* The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC */ #define POSIX_TIME_AT_EPICS_EPOCH 631152000u @@ -170,9 +171,15 @@ private: extern "C" { #endif /* __cplusplus */ -/* All epicsTime routines return (-1,0) for (failure,success) */ +/* epicsTime routines return S_time_ error status values */ #define epicsTimeOK 0 -#define epicsTimeERROR (-1) +#define S_time_noProvider (M_time| 1) /*No time provider*/ +#define S_time_badEvent (M_time| 2) /*Bad event number*/ +#define S_time_badArgs (M_time| 3) /*Invalid arguments*/ +#define S_time_noMemory (M_time| 4) /*Out of memory*/ +#define S_time_unsynchronized (M_time| 5) /*Provider not synchronized*/ +#define S_time_timezone (M_time| 6) /*Invalid timeone*/ +#define S_time_conversion (M_time| 7) /*Time conversion error*/ /*Some special values for eventNumber*/ #define epicsTimeEventCurrentTime 0 diff --git a/src/libCom/osi/os/Darwin/osdTime.cpp b/src/libCom/osi/os/Darwin/osdTime.cpp index f3e6db5dd..c4a7e838c 100644 --- a/src/libCom/osi/os/Darwin/osdTime.cpp +++ b/src/libCom/osi/os/Darwin/osdTime.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -52,13 +53,13 @@ static int done = timeRegister(); int epicsTime_gmtime(const time_t *pAnsiTime, struct tm *pTM) { return gmtime_r(pAnsiTime, pTM) ? - epicsTimeOK : epicsTimeERROR; + epicsTimeOK : errno; } int epicsTime_localtime(const time_t *clock, struct tm *result) { return localtime_r(clock, result) ? - epicsTimeOK : epicsTimeERROR; + epicsTimeOK : errno; } extern "C" epicsShareFunc void diff --git a/src/libCom/osi/os/RTEMS/osdTime.cpp b/src/libCom/osi/os/RTEMS/osdTime.cpp index acefa1b09..b233ec1e5 100644 --- a/src/libCom/osi/os/RTEMS/osdTime.cpp +++ b/src/libCom/osi/os/RTEMS/osdTime.cpp @@ -91,7 +91,7 @@ int epicsTime_gmtime ( const time_t *pAnsiTime, struct tm *pTM ) return epicsTimeOK; } else { - return epicsTimeERROR; + return errno; } } @@ -102,7 +102,7 @@ int epicsTime_localtime ( const time_t *clock, struct tm *result ) return epicsTimeOK; } else { - return epicsTimeERROR; + return errno; } } diff --git a/src/libCom/osi/os/WIN32/osdTime.cpp b/src/libCom/osi/os/WIN32/osdTime.cpp index 877311ffa..9d584879c 100644 --- a/src/libCom/osi/os/WIN32/osdTime.cpp +++ b/src/libCom/osi/os/WIN32/osdTime.cpp @@ -164,7 +164,7 @@ int epicsShareAPI epicsTime_gmtime ( const time_t *pAnsiTime, struct tm *pTM ) SYSTEMTIME st; BOOL status = FileTimeToSystemTime ( &ft, &st ); if ( ! status ) { - return epicsTimeERROR; + return S_time_conversion; } pTM->tm_sec = st.wSecond; // seconds after the minute - [0,59] @@ -193,7 +193,7 @@ int epicsShareAPI epicsTime_localtime ( TIME_ZONE_INFORMATION tzInfo; DWORD tzStatus = GetTimeZoneInformation ( & tzInfo ); if ( tzStatus == TIME_ZONE_ID_INVALID ) { - return epicsTimeERROR; + return S_time_timezone; } // @@ -204,13 +204,13 @@ int epicsShareAPI epicsTime_localtime ( SYSTEMTIME st; BOOL success = FileTimeToSystemTime ( & ft, & st ); if ( ! success ) { - return epicsTimeERROR; + return S_time_conversion; } SYSTEMTIME lst; success = SystemTimeToTzSpecificLocalTime ( & tzInfo, & st, & lst ); if ( ! success ) { - return epicsTimeERROR; + return S_time_conversion; } // @@ -220,7 +220,7 @@ int epicsShareAPI epicsTime_localtime ( FILETIME lft; success = SystemTimeToFileTime ( & lst, & lft ); if ( ! success ) { - return epicsTimeERROR; + return S_time_conversion; } int is_dst = -1; // unknown state of dst @@ -234,14 +234,14 @@ int epicsShareAPI epicsTime_localtime ( success = SystemTimeToFileTime ( & tzInfo.StandardDate, & StandardDateFT ); if ( ! success ) { - return epicsTimeERROR; + return S_time_conversion; } tzInfo.DaylightDate.wYear = st.wYear; FILETIME DaylightDateFT; success = SystemTimeToFileTime ( & tzInfo.DaylightDate, & DaylightDateFT ); if ( ! success ) { - return epicsTimeERROR; + return S_time_conversion; } if ( CompareFileTime ( & lft, & DaylightDateFT ) >= 0 && CompareFileTime ( & lft, & StandardDateFT ) < 0 ) { diff --git a/src/libCom/osi/os/posix/osdTime.cpp b/src/libCom/osi/os/posix/osdTime.cpp index 679c6e376..7713a2c25 100644 --- a/src/libCom/osi/os/posix/osdTime.cpp +++ b/src/libCom/osi/os/posix/osdTime.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "osiSock.h" @@ -36,7 +37,7 @@ struct timezone tz; if (gettimeofday (&tv, &tz)) - return epicsTimeERROR; + return errno; *pDest = epicsTime(tv); return epicsTimeOK; @@ -68,7 +69,7 @@ int epicsTime_gmtime ( const time_t *pAnsiTime, return epicsTimeOK; } else { - return epicsTimeERROR; + return errno; } } @@ -80,7 +81,7 @@ int epicsTime_localtime ( const time_t *clock, return epicsTimeOK; } else { - return epicsTimeERROR; + return errno; } } diff --git a/src/libCom/osi/osiNTPTime.c b/src/libCom/osi/osiNTPTime.c index 64362b2e8..d22df861b 100644 --- a/src/libCom/osi/osiNTPTime.c +++ b/src/libCom/osi/osiNTPTime.c @@ -164,7 +164,7 @@ static void NTPTimeSync(void *dummy) } if (timespecNow.tv_sec <= POSIX_TIME_AT_EPICS_EPOCH || - epicsTimeFromTimespec(&timeNow, ×pecNow) == epicsTimeERROR) { + epicsTimeFromTimespec(&timeNow, ×pecNow) != epicsTimeOK) { errlogPrintf("NTPTimeSync: Bad time received from NTP server\n"); NTPTimePvt.synchronized = 0; continue; @@ -213,7 +213,7 @@ static int NTPTimeGetCurrent(epicsTimeStamp *pDest) epicsUInt32 ticksSince; if (!NTPTimePvt.synchronized) - return epicsTimeERROR; + return S_time_unsynchronized; epicsMutexMustLock(NTPTimePvt.lock); diff --git a/src/std/dev/devGeneralTime.c b/src/std/dev/devGeneralTime.c index c656c85db..0cce00d4b 100644 --- a/src/std/dev/devGeneralTime.c +++ b/src/std/dev/devGeneralTime.c @@ -37,7 +37,7 @@ static int getCurrentTime(double * pseconds) { epicsTimeStamp ts; - if (epicsTimeERROR != epicsTimeGetCurrent(&ts)) { + if (epicsTimeOK == epicsTimeGetCurrent(&ts)) { *pseconds = ts.secPastEpoch + ((double)(ts.nsec)) * 1e-9; return 0; } From 53d01f6fb437ff2fc87157f71cb007486d8956ea Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 3 Jun 2015 00:15:39 -0500 Subject: [PATCH 2/2] Show how to make time providers backwards-compatible --- documentation/RELEASE_NOTES.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 48dacb281..5a3f74280 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -29,6 +29,19 @@ it in source code will no longer compile. The identifier epicsTimeOK still exist and has the value 0 as before, so most code that uses these APIs can be changed in a way that is backwards-compatible with the previous return status.

+

Time providers that have to return a status value and still need to be built +with earlier versions of Base can define the necessary status symbols like this:

+ +
+#include "epicsTime.h"
+
+#ifndef M_time
+/* S_time_... status values were not provided before Base 3.16 */
+#define S_time_unsynchronized epicsTimeERROR
+#define S_time_...whatever... epicsTimeERROR
+#endif
+
+

Callback subsystem API

Added a new macro callbackGetPriority(prio, callback) to the