libCom: Add a High-Resolution Time Provider on MacOS

Since Apple don't support clock_gettime(CLOCK_REALTIME) I added a
new time provider that uses the Mach kernel Clock service to get
nanosecond resolution time.
This commit is contained in:
Andrew Johnson
2013-03-13 14:48:34 -05:00
parent c767958539
commit 738b8ca55f
3 changed files with 97 additions and 1 deletions

View File

@@ -13,6 +13,16 @@
<!-- Insert new items immediately below here ... -->
<h4>High-Resolution Time Provider on MacOS</h4>
<p>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.</p>
<h4>Time drift in periodic scans</h4>
<p>The implementation of the periodic scan code has been modified to remove

View File

@@ -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 <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mach/mach.h>
#include <mach/clock.h>
#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;
}
}

View File

@@ -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)