diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 28558de46..98c9415b1 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,16 @@ +

High-Resolution Time Provider on MacOS

+ +

MacOS does not provide the clock_gettime() API with CLOCK_REALTIME that other +Posix systems implement, so we previously used gettimeofday() to fetch the +current date & time from the OS. That older routine only provides the time with +a resolution of 1 microsecond though, whereas clock_gettime() gives results with +a nanosecond resolution. This release uses a new MachTime time provider on +MacOS which uses the Mach Kernel's CALENDAR_CLOCK service to fetch the time, and +provides nanosecond resolution.

+

Time drift in periodic scans

The implementation of the periodic scan code has been modified to remove diff --git a/src/libCom/osi/os/Darwin/osdTime.cpp b/src/libCom/osi/os/Darwin/osdTime.cpp new file mode 100644 index 000000000..f3e6db5dd --- /dev/null +++ b/src/libCom/osi/os/Darwin/osdTime.cpp @@ -0,0 +1,86 @@ +/*************************************************************************\ +* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* 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. +\*************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "osiSock.h" + +#define epicsExportSharedSymbols +#include "cantProceed.h" +#include "epicsTime.h" +#include "generalTimeSup.h" + +static clock_serv_t host_clock; + +extern "C" { +static int osdTimeGetCurrent (epicsTimeStamp *pDest) +{ + mach_timespec_t mts; + struct timespec ts; + + clock_get_time(host_clock, &mts); + ts.tv_sec = mts.tv_sec; + ts.tv_nsec = mts.tv_nsec; + *pDest = epicsTime(ts); + return epicsTimeOK; +} +} // extern "C" + + +static int timeRegister(void) +{ + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &host_clock); + + generalTimeCurrentTpRegister("MachTime", \ + LAST_RESORT_PRIORITY, osdTimeGetCurrent); + return 1; +} +static int done = timeRegister(); + + +int epicsTime_gmtime(const time_t *pAnsiTime, struct tm *pTM) +{ + return gmtime_r(pAnsiTime, pTM) ? + epicsTimeOK : epicsTimeERROR; +} + +int epicsTime_localtime(const time_t *clock, struct tm *result) +{ + return localtime_r(clock, result) ? + epicsTimeOK : epicsTimeERROR; +} + +extern "C" epicsShareFunc void +convertDoubleToWakeTime(double timeout, struct timespec *wakeTime) +{ + mach_timespec_t now; + struct timespec wait; + + clock_get_time(host_clock, &now); + + if (timeout<0.0) + timeout = 0.0; + else if(timeout>3600.0) + timeout = 3600.0; + + wait.tv_sec = static_cast< long >(timeout); + wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9); + + wakeTime->tv_sec = now.tv_sec + wait.tv_sec; + wakeTime->tv_nsec = now.tv_nsec + wait.tv_nsec; + if (wakeTime->tv_nsec >= 1000000000L) { + wakeTime->tv_nsec -= 1000000000L; + ++wakeTime->tv_sec; + } +} diff --git a/src/libCom/osi/os/posix/osdTime.cpp b/src/libCom/osi/os/posix/osdTime.cpp index 62939a427..987629f51 100644 --- a/src/libCom/osi/os/posix/osdTime.cpp +++ b/src/libCom/osi/os/posix/osdTime.cpp @@ -24,7 +24,7 @@ #define TIME_INIT ClockTime_Init(CLOCKTIME_NOSYNC) #else - /* Some posix systems like Darwin don't have CLOCK_REALTIME */ + /* Some posix systems may not have CLOCK_REALTIME */ #define TIME_INIT generalTimeCurrentTpRegister("GetTimeOfDay", \ LAST_RESORT_PRIORITY, osdTimeGetCurrent)