From 6aec8d9bcb4ee7f0c68aed5abddcc034fbbe45f4 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 25 Aug 2015 18:09:35 -0400 Subject: [PATCH 1/7] libCom/osi: fetch monotonic time --- src/libCom/osi/Makefile | 1 + src/libCom/osi/epicsTime.h | 11 ++++ src/libCom/osi/os/Darwin/osdMonotonic.c | 32 +++++++++++ src/libCom/osi/os/Darwin/osdTime.cpp | 3 + src/libCom/osi/os/RTEMS/osdTime.cpp | 3 + src/libCom/osi/os/WIN32/osdMonotonic.c | 53 +++++++++++++++++ src/libCom/osi/os/WIN32/osdTime.cpp | 3 + src/libCom/osi/os/iOS/osdMonotonic.c | 31 ++++++++++ src/libCom/osi/os/posix/osdMonotonic.c | 75 +++++++++++++++++++++++++ src/libCom/osi/os/posix/osdTime.cpp | 3 + src/libCom/osi/os/vxWorks/osdTime.cpp | 2 + src/libCom/test/epicsTimeTest.cpp | 45 ++++++++++++++- 12 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 src/libCom/osi/os/Darwin/osdMonotonic.c create mode 100644 src/libCom/osi/os/WIN32/osdMonotonic.c create mode 100644 src/libCom/osi/os/iOS/osdMonotonic.c create mode 100644 src/libCom/osi/os/posix/osdMonotonic.c diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile index c06a862ed..ecbf4c23b 100644 --- a/src/libCom/osi/Makefile +++ b/src/libCom/osi/Makefile @@ -119,6 +119,7 @@ Com_SRCS += osdMutex.c Com_SRCS += osdSpin.c Com_SRCS += osdEvent.c Com_SRCS += osdTime.cpp +Com_SRCS += osdMonotonic.c Com_SRCS += osdProcess.c Com_SRCS += osdNetIntf.c Com_SRCS += osdMessageQueue.c diff --git a/src/libCom/osi/epicsTime.h b/src/libCom/osi/epicsTime.h index 149f6f2d3..862bc22d2 100644 --- a/src/libCom/osi/epicsTime.h +++ b/src/libCom/osi/epicsTime.h @@ -258,6 +258,17 @@ epicsShareFunc void epicsShareAPI epicsTimeShow ( epicsShareFunc int epicsShareAPI epicsTime_localtime ( const time_t * clock, struct tm * result ); 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() + */ +epicsShareFunc epicsUInt64 epicsMonotonicResolution(void); +/* Fetch monotonic counter, return is nano-seconds since an unspecified time */ +epicsShareFunc epicsUInt64 epicsMonotonicGet(void); + +#ifdef EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE +epicsShareFunc void osdMonotonicInit(void); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/libCom/osi/os/Darwin/osdMonotonic.c b/src/libCom/osi/os/Darwin/osdMonotonic.c new file mode 100644 index 000000000..50ca82ef6 --- /dev/null +++ b/src/libCom/osi/os/Darwin/osdMonotonic.c @@ -0,0 +1,32 @@ +/*************************************************************************\ +* Copyright (c) 2015 Michael Davidsaver +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include +#include + +#define epicsExportSharedSymbols +#include "dbDefs.h" +#include "errlog.h" +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE +#include "epicsTime.h" +#include "generalTimeSup.h" + +void osdMonotonicInit(void) +{ + /* no-op */ +} + +epicsUInt64 epicsMonotonicResolution(void) +{ + return 1; /* TODO, how to find ? */ +} + +epicsUInt64 epicsMonotonicGet(void) +{ + uint64_t val = mach_absolute_time(), ret; + absolutetime_to_nanoseconds(val, &ret); + return ret; +} diff --git a/src/libCom/osi/os/Darwin/osdTime.cpp b/src/libCom/osi/os/Darwin/osdTime.cpp index 72b3dc874..7bddc7da2 100644 --- a/src/libCom/osi/os/Darwin/osdTime.cpp +++ b/src/libCom/osi/os/Darwin/osdTime.cpp @@ -19,6 +19,7 @@ #define epicsExportSharedSymbols #include "cantProceed.h" +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" @@ -45,6 +46,8 @@ static int timeRegister(void) generalTimeCurrentTpRegister("MachTime", \ LAST_RESORT_PRIORITY, osdTimeGetCurrent); + + osdMonotonicInit(); return 1; } static int done = timeRegister(); diff --git a/src/libCom/osi/os/RTEMS/osdTime.cpp b/src/libCom/osi/os/RTEMS/osdTime.cpp index 4947c568e..a9d5c2ea6 100644 --- a/src/libCom/osi/os/RTEMS/osdTime.cpp +++ b/src/libCom/osi/os/RTEMS/osdTime.cpp @@ -20,6 +20,7 @@ #include #include #include +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "osdTime.h" #include "osiNTPTime.h" @@ -37,6 +38,8 @@ void osdTimeRegister(void) /* Init NTP first so it can be used to sync ClockTime */ NTPTime_Init(100); ClockTime_Init(CLOCKTIME_SYNC); + + osdMonotonicInit(); } int osdNTPGet(struct timespec *ts) diff --git a/src/libCom/osi/os/WIN32/osdMonotonic.c b/src/libCom/osi/os/WIN32/osdMonotonic.c new file mode 100644 index 000000000..342ee7d60 --- /dev/null +++ b/src/libCom/osi/os/WIN32/osdMonotonic.c @@ -0,0 +1,53 @@ +/*************************************************************************\ +* Copyright (c) 2015 Michael Davidsaver +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include + +#define epicsExportSharedSymbols +#include "dbDefs.h" +#include "errlog.h" +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE +#include "epicsTime.h" +#include "generalTimeSup.h" + +static unsigned char osdUsePrefCounter; +static epicsUInt64 osdMonotonicResolution; + +void osdMonotonicInit(void) +{ + LARGE_INTEGER freq, val; + + if(!QueryPerformanceFrequency(&freq) || + !QueryPerformanceCounter(&val)) + { + double period = 1.0/freq.QuadPart; + osdMonotonicResolution = period*1e9; + osdUsePrefCounter = 1; + } else { + osdMonotonicResolution = 1e6; /* 1 ms TODO place holder */ + } +} + +epicsUInt64 epicsMonotonicResolution(void) +{ + return osdMonotonicResolution; +} + +epicsUInt64 epicsMonotonicGet(void) +{ + LARGE_INTEGER val; + if(osdUsePrefCounter) { + if(!QueryPerformanceCounter(&val)) { + errMessage(errlogMinor, "Warning: failed to fetch performance counter\n"); + return 0; + } else + return val.QuadPart; + } else { + epicsUInt64 ret = GetTickCount(); + ret *= 1000000; + return ret; + } +} diff --git a/src/libCom/osi/os/WIN32/osdTime.cpp b/src/libCom/osi/os/WIN32/osdTime.cpp index 2ee0d3066..348fe7c2f 100644 --- a/src/libCom/osi/os/WIN32/osdTime.cpp +++ b/src/libCom/osi/os/WIN32/osdTime.cpp @@ -31,6 +31,7 @@ // EPICS // #define epicsExportSharedSymbols +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" #include "epicsTimer.h" @@ -106,6 +107,8 @@ static int timeRegister(void) generalTimeCurrentTpRegister("PerfCounter", 150, osdTimeGetCurrent); pCurrentTime->startPLL (); + + osdMonotonicInit(); return 1; } static int done = timeRegister(); diff --git a/src/libCom/osi/os/iOS/osdMonotonic.c b/src/libCom/osi/os/iOS/osdMonotonic.c new file mode 100644 index 000000000..0c2c7718f --- /dev/null +++ b/src/libCom/osi/os/iOS/osdMonotonic.c @@ -0,0 +1,31 @@ +/*************************************************************************\ +* Copyright (c) 2015 Michael Davidsaver +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#import + +#define epicsExportSharedSymbols +#include "dbDefs.h" +#include "errlog.h" +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE +#include "epicsTime.h" +#include "generalTimeSup.h" + +void osdMonotonicInit(void) +{ + /* no-op */ +} + +epicsUInt64 epicsMonotonicResolution(void) +{ + return 1; /* TODO, how to find ? */ +} + +epicsUInt64 epicsMonotonicGet(void) +{ + uint64_t val = mach_absolute_time(), ret; + absolutetime_to_nanoseconds(val, &ret); + return ret; +} diff --git a/src/libCom/osi/os/posix/osdMonotonic.c b/src/libCom/osi/os/posix/osdMonotonic.c new file mode 100644 index 000000000..203702dd5 --- /dev/null +++ b/src/libCom/osi/os/posix/osdMonotonic.c @@ -0,0 +1,75 @@ +/*************************************************************************\ +* Copyright (c) 2015 Michael Davidsaver +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#define epicsExportSharedSymbols +#include "dbDefs.h" +#include "errlog.h" +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE +#include "epicsTime.h" +#include "generalTimeSup.h" + +static clockid_t osdMonotonicID; +static epicsUInt64 osdMonotonicResolution; + +void osdMonotonicInit(void) +{ + unsigned i; +clockid_t ids[] = { +#ifdef CLOCK_MONOTONIC_RAW + CLOCK_MONOTONIC_RAW, /* Linux specific */ +#endif +#ifdef CLOCK_HIGHRES + CLOCK_HIGHRES, /* solaris specific */ +#endif +#ifdef CLOCK_MONOTONIC + CLOCK_MONOTONIC, /* Linux, RTEMS, and probably others */ +#endif + /* fallback and vxWorks, not actually monotonic, but always available */ + CLOCK_REALTIME + }; + + for(i=0; i #include +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "osiNTPTime.h" #include "osiClockTime.h" @@ -63,6 +64,7 @@ static int timeRegister(void) } else { ClockTime_Init(CLOCKTIME_NOSYNC); } + osdMonotonicInit(); return 1; } static int done = timeRegister(); diff --git a/src/libCom/test/epicsTimeTest.cpp b/src/libCom/test/epicsTimeTest.cpp index 55ad43cdd..8eb8de6d4 100644 --- a/src/libCom/test/epicsTimeTest.cpp +++ b/src/libCom/test/epicsTimeTest.cpp @@ -38,12 +38,53 @@ static const unsigned uSecPerSec = 1000u * mSecPerSec; static const unsigned nSecPerSec = 1000u * uSecPerSec; static const double precisionEPICS = 1.0 / nSecPerSec; +static void crossCheck(double delay) +{ + double mindelta = 2*epicsMonotonicResolution()*1e-9, + tres = epicsThreadSleepQuantum(); + epicsUInt64 A = epicsMonotonicGet(); + epicsThreadSleep(delay); + epicsUInt64 B = epicsMonotonicGet(); + + double actual = (B-A)*1e-9, percent; + + if(mindelta Date: Mon, 11 Jan 2016 21:49:49 -0500 Subject: [PATCH 2/7] move EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE before all local includes --- src/libCom/osi/os/Darwin/osdMonotonic.c | 2 +- src/libCom/osi/os/Darwin/osdTime.cpp | 2 +- src/libCom/osi/os/RTEMS/osdTime.cpp | 2 +- src/libCom/osi/os/WIN32/osdMonotonic.c | 2 +- src/libCom/osi/os/iOS/osdMonotonic.c | 2 +- src/libCom/osi/os/posix/osdMonotonic.c | 2 +- src/libCom/osi/os/posix/osdTime.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libCom/osi/os/Darwin/osdMonotonic.c b/src/libCom/osi/os/Darwin/osdMonotonic.c index 50ca82ef6..9ce14fa8e 100644 --- a/src/libCom/osi/os/Darwin/osdMonotonic.c +++ b/src/libCom/osi/os/Darwin/osdMonotonic.c @@ -8,9 +8,9 @@ #include #define epicsExportSharedSymbols +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "dbDefs.h" #include "errlog.h" -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" diff --git a/src/libCom/osi/os/Darwin/osdTime.cpp b/src/libCom/osi/os/Darwin/osdTime.cpp index 7bddc7da2..315caeb9b 100644 --- a/src/libCom/osi/os/Darwin/osdTime.cpp +++ b/src/libCom/osi/os/Darwin/osdTime.cpp @@ -15,11 +15,11 @@ #include #include +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "osiSock.h" #define epicsExportSharedSymbols #include "cantProceed.h" -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" diff --git a/src/libCom/osi/os/RTEMS/osdTime.cpp b/src/libCom/osi/os/RTEMS/osdTime.cpp index a9d5c2ea6..1350c1cf2 100644 --- a/src/libCom/osi/os/RTEMS/osdTime.cpp +++ b/src/libCom/osi/os/RTEMS/osdTime.cpp @@ -12,6 +12,7 @@ #include #include +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include #include #include @@ -20,7 +21,6 @@ #include #include #include -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "osdTime.h" #include "osiNTPTime.h" diff --git a/src/libCom/osi/os/WIN32/osdMonotonic.c b/src/libCom/osi/os/WIN32/osdMonotonic.c index 342ee7d60..e7da25da4 100644 --- a/src/libCom/osi/os/WIN32/osdMonotonic.c +++ b/src/libCom/osi/os/WIN32/osdMonotonic.c @@ -7,9 +7,9 @@ #include #define epicsExportSharedSymbols +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "dbDefs.h" #include "errlog.h" -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" diff --git a/src/libCom/osi/os/iOS/osdMonotonic.c b/src/libCom/osi/os/iOS/osdMonotonic.c index 0c2c7718f..0eab29c91 100644 --- a/src/libCom/osi/os/iOS/osdMonotonic.c +++ b/src/libCom/osi/os/iOS/osdMonotonic.c @@ -7,9 +7,9 @@ #import #define epicsExportSharedSymbols +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "dbDefs.h" #include "errlog.h" -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" diff --git a/src/libCom/osi/os/posix/osdMonotonic.c b/src/libCom/osi/os/posix/osdMonotonic.c index 203702dd5..00c9c2871 100644 --- a/src/libCom/osi/os/posix/osdMonotonic.c +++ b/src/libCom/osi/os/posix/osdMonotonic.c @@ -5,9 +5,9 @@ \*************************************************************************/ #define epicsExportSharedSymbols +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "dbDefs.h" #include "errlog.h" -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" diff --git a/src/libCom/osi/os/posix/osdTime.cpp b/src/libCom/osi/os/posix/osdTime.cpp index d56fc15d8..1952babd9 100644 --- a/src/libCom/osi/os/posix/osdTime.cpp +++ b/src/libCom/osi/os/posix/osdTime.cpp @@ -13,11 +13,11 @@ #include #include +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "osiSock.h" #define epicsExportSharedSymbols #include "cantProceed.h" -#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTime.h" #include "generalTimeSup.h" From 1c00e79b6b0c45f020ede5a0b6806d3ae5b37ca4 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 14 Jun 2017 17:02:10 +0200 Subject: [PATCH 3/7] monotonic: fix osx --- src/libCom/osi/os/Darwin/osdMonotonic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libCom/osi/os/Darwin/osdMonotonic.c b/src/libCom/osi/os/Darwin/osdMonotonic.c index 9ce14fa8e..6f8cb85af 100644 --- a/src/libCom/osi/os/Darwin/osdMonotonic.c +++ b/src/libCom/osi/os/Darwin/osdMonotonic.c @@ -1,10 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2015 Michael Davidsaver +* Copyright (c) 2017 Michael Davidsaver * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -#include +#include #include #define epicsExportSharedSymbols @@ -14,19 +14,21 @@ #include "epicsTime.h" #include "generalTimeSup.h" +/* see https://developer.apple.com/library/content/qa/qa1398/_index.html */ +static mach_timebase_info_data_t tbinfo; + void osdMonotonicInit(void) { - /* no-op */ + (void)mach_timebase_info(&tbinfo); } epicsUInt64 epicsMonotonicResolution(void) { - return 1; /* TODO, how to find ? */ + return 1e-9 * tbinfo.numer / tbinfo.denom; } epicsUInt64 epicsMonotonicGet(void) { uint64_t val = mach_absolute_time(), ret; - absolutetime_to_nanoseconds(val, &ret); - return ret; + return val * tbinfo.numer / tbinfo.denom; } From 06b2d4bb76c829f30bb0b4d4c4627a056671112d Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 21 Dec 2015 14:35:35 -0500 Subject: [PATCH 4/7] db/test: dbStressTest use monotonic Conflicts: src/ioc/db/test/dbStressLock.c --- src/ioc/db/test/dbStressLock.c | 59 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/ioc/db/test/dbStressLock.c b/src/ioc/db/test/dbStressLock.c index 376587975..aed0116e0 100644 --- a/src/ioc/db/test/dbStressLock.c +++ b/src/ioc/db/test/dbStressLock.c @@ -27,7 +27,10 @@ #include "epicsSpin.h" #include "epicsThread.h" #include "epicsMutex.h" +#include "epicsEvent.h" +#include "epicsMath.h" #include "dbCommon.h" +#include "epicsTime.h" #include "dbLockPvt.h" #include "dbStaticLib.h" @@ -40,10 +43,6 @@ #include "xRecord.h" -#if defined(CLOCK_REALTIME) && defined(CLOCK_MONOTONIC) && !defined(_WIN32) -# define TIME_STATS -#endif - #define testIntOk1(A, OP, B) testOk((A) OP (B), "%s (%d) %s %s (%d)", #A, A, #OP, #B, B); #define testPtrOk1(A, OP, B) testOk((A) OP (B), "%s (%p) %s %s (%p)", #A, A, #OP, #B, B); @@ -64,10 +63,9 @@ static dbCommon **precords; typedef struct { int id; unsigned long N[3]; -#ifdef TIME_STATS double X[3]; double X2[3]; -#endif + double min[3], max[3]; unsigned int done; epicsEventId donevent; @@ -158,25 +156,19 @@ void doreTarget(workerPriv *p) static void worker(void *raw) { -#ifdef TIME_STATS - struct timespec before; -#endif + unsigned init = 1; workerPriv *priv = raw; testDiag("worker %d is %p", priv->id, epicsThreadGetIdSelf()); -#ifdef TIME_STATS - clock_gettime(CLOCK_MONOTONIC, &before); -#endif - while(!priv->done) { + epicsUInt64 after, before; double sel = getRand(); -#ifdef TIME_STATS - struct timespec after; double duration; -#endif - int act; + + before = epicsMonotonicGet(); + if(sel<0.33) { doSingle(priv); act = 0; @@ -188,19 +180,18 @@ void worker(void *raw) act = 2; } -#ifdef TIME_STATS - clock_gettime(CLOCK_MONOTONIC, &after); - - duration = (double)((long)after.tv_nsec - (long)before.tv_nsec); - duration *= 1e-9; - duration += (double)(after.tv_sec - before.tv_sec); -#endif + after = epicsMonotonicGet(); + duration = (after-before)*1e-9; priv->N[act]++; -#ifdef TIME_STATS priv->X[act] += duration; priv->X2[act] += duration*duration; -#endif + if(durationmin[act] || init) { + priv->min[act] = duration; + init = 0; + } + if(duration>priv->max[act]) + priv->max[act] = duration; } epicsEventMustTrigger(priv->donevent); @@ -333,12 +324,18 @@ MAIN(dbStressTest) testDiag("Statistics"); for(i=0; i0); testOk1(priv[i].N[1]>0); From 62db42bf356b3186d8caedd6df0c26bbede59830 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 23 Oct 2017 11:27:51 -0500 Subject: [PATCH 5/7] Delete unused variable --- src/libCom/osi/os/Darwin/osdMonotonic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libCom/osi/os/Darwin/osdMonotonic.c b/src/libCom/osi/os/Darwin/osdMonotonic.c index 6f8cb85af..2f81d002b 100644 --- a/src/libCom/osi/os/Darwin/osdMonotonic.c +++ b/src/libCom/osi/os/Darwin/osdMonotonic.c @@ -29,6 +29,6 @@ epicsUInt64 epicsMonotonicResolution(void) epicsUInt64 epicsMonotonicGet(void) { - uint64_t val = mach_absolute_time(), ret; + uint64_t val = mach_absolute_time(); return val * tbinfo.numer / tbinfo.denom; } From a1d2f337f44e840493a5aa6e5bff74c2833529a7 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 23 Oct 2017 11:30:29 -0500 Subject: [PATCH 6/7] Initial VxWorks support code Implemented for both PowerPC and i86. Builds, but not tested yet. --- src/libCom/osi/os/vxWorks/osdMonotonic.c | 92 ++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/libCom/osi/os/vxWorks/osdMonotonic.c diff --git a/src/libCom/osi/os/vxWorks/osdMonotonic.c b/src/libCom/osi/os/vxWorks/osdMonotonic.c new file mode 100644 index 000000000..6a7abadbf --- /dev/null +++ b/src/libCom/osi/os/vxWorks/osdMonotonic.c @@ -0,0 +1,92 @@ +/*************************************************************************\ +* Copyright (c) 2017 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. +\*************************************************************************/ + +#define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h> + +#include + +#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE +#include "epicsTypes.h" +#include "epicsTime.h" +#include "epicsFindSymbol.h" + + +#define NS_PER_SEC 1000000000 + +union timebase { + UINT32 u32[2]; /* vxTimeBaseGet() */ + INT64 i64; /* pentiumTscGet64() */ + UINT64 u64; /* epicsMonotonicGet() */ +}; + +static epicsUInt64 ticksPerSec; + + +#if CPU_FAMILY == PPC +#include + +#define TIMEBASEGET(TB) \ + vxTimeBaseGet(&TB.u32[0], &TB.u32[1]) + +typedef epicsUInt64 (*sysTimeBaseFreq_t)(void); + +void osdMonotonicInit(void) +{ + sysTimeBaseFreq_t sysTimeBaseFreq = + (sysTimeBaseFreq_t) epicsFindSymbol("_sysTimeBaseFreq"); + + if (sysTimeBaseFreq) { + ticksPerSec = sysTimeBaseFreq(); + return; + } + + printf("Warning: BSP routine sysTimeBaseFreq() not found,\n" + "can't set up monotonic time source.\n"); + ticksPerSec = 0; +} + + +#elif CPU_FAMILY == I80X86 + +#include +#include + +#define TIMEBASEGET(TB) \ + pentiumTscGet64(&TB.i64) + +void osdMonotonicInit(void) +{ + ticksPerSec = vxCpuIdGetFreq(); + + if (!ticksPerSec) + printf("Warning: Failed to set up monotonic time source.\n"); +} + + +#else + #error CPU Family not supported yet! +#endif + + +epicsUInt64 epicsMonotonicResolution(void) +{ + if (!ticksPerSec) + return 0; + + return NS_PER_SEC / ticksPerSec; +} + +epicsUInt64 epicsMonotonicGet(void) +{ + union timebase tbNow; + + if (!ticksPerSec) + return 0; + + TIMEBASEGET(tbNow); + return tbNow.u64 / (ticksPerSec / NS_PER_SEC); +} From 49d638be979ea7fad86d6d68e98d692ad9e62e1e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 27 Oct 2017 15:17:38 -0500 Subject: [PATCH 7/7] VxWorks osdMonotonic implementation PowerPC time-base frequencies are 32-bit. Adjust when warnings are printed. Use long double to calculate time from time-base. --- src/libCom/osi/os/vxWorks/osdMonotonic.c | 47 +++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/libCom/osi/os/vxWorks/osdMonotonic.c b/src/libCom/osi/os/vxWorks/osdMonotonic.c index 6a7abadbf..e0c6b2278 100644 --- a/src/libCom/osi/os/vxWorks/osdMonotonic.c +++ b/src/libCom/osi/os/vxWorks/osdMonotonic.c @@ -8,11 +8,11 @@ #define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h> #include +#include #define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE #include "epicsTypes.h" #include "epicsTime.h" -#include "epicsFindSymbol.h" #define NS_PER_SEC 1000000000 @@ -23,30 +23,35 @@ union timebase { UINT64 u64; /* epicsMonotonicGet() */ }; -static epicsUInt64 ticksPerSec; - #if CPU_FAMILY == PPC #include +#include "epicsFindSymbol.h" + +/* On PowerPC the timebase counter runs at a rate related to the + * bus clock and its frequency should always fit into a UINT32. + */ + +static epicsUInt32 ticksPerSec; #define TIMEBASEGET(TB) \ vxTimeBaseGet(&TB.u32[0], &TB.u32[1]) -typedef epicsUInt64 (*sysTimeBaseFreq_t)(void); - void osdMonotonicInit(void) { + typedef epicsUInt32 (*sysTimeBaseFreq_t)(void); sysTimeBaseFreq_t sysTimeBaseFreq = (sysTimeBaseFreq_t) epicsFindSymbol("_sysTimeBaseFreq"); if (sysTimeBaseFreq) { ticksPerSec = sysTimeBaseFreq(); - return; - } - printf("Warning: BSP routine sysTimeBaseFreq() not found,\n" - "can't set up monotonic time source.\n"); - ticksPerSec = 0; + if (!ticksPerSec) + printf("Warning: Failed to set up monotonic time source.\n"); + /* Warn here only if the BSP routine exists but returned 0 */ + } + else + ticksPerSec = 0; /* Warn on first use */ } @@ -55,6 +60,12 @@ void osdMonotonicInit(void) #include #include +/* On Intel the timebase counter frequency is returned by the OS as a + * UINT64. Some CPUs may count at multi-GHz rates so we need 64 bits. + */ + +static epicsUInt64 ticksPerSec; + #define TIMEBASEGET(TB) \ pentiumTscGet64(&TB.i64) @@ -68,7 +79,7 @@ void osdMonotonicInit(void) #else - #error CPU Family not supported yet! + #error This CPU family not supported yet! #endif @@ -84,9 +95,19 @@ epicsUInt64 epicsMonotonicGet(void) { union timebase tbNow; - if (!ticksPerSec) + if (!ticksPerSec) { + static int warned = 0; + + if (!warned) { + printf("Warning: Monotonic time source is not available.\n"); + warned = 1; + } return 0; + } TIMEBASEGET(tbNow); - return tbNow.u64 / (ticksPerSec / NS_PER_SEC); + /* Using a long double for the calculation below to preserve + * as many bits in the mantissa as possible. + */ + return ((long double) tbNow.u64) * NS_PER_SEC / ticksPerSec; }