From 44b3532e07d2e3790a75ccd5a75f19deefa71e82 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 1 Mar 2015 23:57:01 -0500 Subject: Implement POSIX clock_gettime(3) for systems that lack it (like Mac OS X). On Mac OS X it will get proper nanosecond precision; elsewhere, only microseconds. Hides the conformance failure from the rest of the code. All regression tests pass. --- SConstruct | 9 +++++++++ clock_gettime.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ gpsutils.c | 6 ------ libgps.h | 2 ++ libgps_dbus.c | 1 - libgpsd_core.c | 6 ------ ntpshmread.c | 9 --------- ppsthread.c | 15 --------------- 8 files changed, 58 insertions(+), 37 deletions(-) create mode 100644 clock_gettime.c diff --git a/SConstruct b/SConstruct index 7b2f6cf7..e82857d5 100644 --- a/SConstruct +++ b/SConstruct @@ -751,6 +751,14 @@ pid_t getsid(pid_t pid); } # endif #endif +#ifndef HAVE_CLOCK_GETTIME +# ifdef __cplusplus +extern "C" { +typedef int clockid_t; +#define CLOCK_REALTIME 0 +int clock_gettime(clockid_t, struct timespec *); +# endif +#endif #define GPSD_CONFIG_H @@ -823,6 +831,7 @@ libgpsd_version = "%d.%d.%d" %(libgpsd_version_soname, libgpsd_version_age, libg libgps_sources = [ "ais_json.c", "bits.c", + "clock_gettime.c", "daemon.c", "gpsutils.c", "gpsdclient.c", diff --git a/clock_gettime.c b/clock_gettime.c new file mode 100644 index 00000000..b6b7dff1 --- /dev/null +++ b/clock_gettime.c @@ -0,0 +1,47 @@ +/* + * Simulate ANSI/POSIX conformance on platforms that don't have it + * + * This file is Copyright (c) 2010 by the GPSD project + * BSD terms apply: see the file COPYING in the distribution root for details. + */ +#include +#include + +#include "compiler.h" + +#ifdef __MACH__ +#include +#include +#endif + +#ifndef HAVE_CLOCK_GETTIME +int clock_gettime(clockid_t clk_id UNUSED, struct timespec *tp) +{ +#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + ts.tv_sec = mts.tv_sec; + ts.tv_nsec = mts.tv_nsec; +#else + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) + return -1; + tp->ts_sec = tv.tv_sec; + tp->ts_nsec = tv.tv_usec * 1000; + /* paranoid programming */ + if (1000000 <= (tv)->tv_usec) { + (tv)->tv_usec -= 1000000; + (tv)->tv_sec++; + } else if (0 > (tv)->tv_usec) { + (tv)->tv_usec += 1000000; + (tv)->tv_sec--; + } + return 0; +#endif /* __MACH__ */ +} +#endif /* HAVE_CLOCK_GETTIME */ + +/* end */ diff --git a/gpsutils.c b/gpsutils.c index fa15bc49..e7000f70 100644 --- a/gpsutils.c +++ b/gpsutils.c @@ -299,15 +299,9 @@ void gps_merge_fix( /*@ out @*/ struct gps_fix_t *to, * near microSec. Do not use near PPS which is nanoSec precise */ timestamp_t timestamp(void) { -#ifdef HAVE_CLOCK_GETTIME struct timespec ts; /*@i2@*/(void)clock_gettime(CLOCK_REALTIME, &ts); /*@i3@*/return (timestamp_t)(ts.tv_sec + ts.tv_nsec * 1e-9); -#else - struct timeval tv; - (void)gettimeofday(&tv, NULL); - return (timestamp_t)(tv.tv_sec + tv.tv_usec * 1e-6); -#endif } time_t mkgmtime(register struct tm * t) diff --git a/libgps.h b/libgps.h index 914c4df2..9ef0ae37 100644 --- a/libgps.h +++ b/libgps.h @@ -10,6 +10,8 @@ #define SHM_PSEUDO_FD -1 #define DBUS_PSEUDO_FD -2 +#include "compiler.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/libgps_dbus.c b/libgps_dbus.c index 092e0bdf..826f12d4 100644 --- a/libgps_dbus.c +++ b/libgps_dbus.c @@ -14,7 +14,6 @@ #include "gps.h" #include "gpsd_config.h" -#include "compiler.h" #include "libgps.h" #if defined(DBUS_EXPORT_ENABLE) && !defined(S_SPLINT_S) diff --git a/libgpsd_core.c b/libgpsd_core.c index 210aa596..a1a1a44e 100644 --- a/libgpsd_core.c +++ b/libgpsd_core.c @@ -1658,13 +1658,7 @@ void ntp_latch(struct gps_device_t *device, struct timedelta_t /*@out@*/*td) /* this should be an invariant of the way this function is called */ assert(isnan(device->newdata.time)==0); -#ifdef HAVE_CLOCK_GETTIME /*@i2@*/(void)clock_gettime(CLOCK_REALTIME, &td->clock); -#else - struct timeval clock_tv; - (void)gettimeofday(&clock_tv, NULL); - TVTOTS(&td->clock, &clock_tv); -#endif /* HAVE_CLOCK_GETTIME */ fix_time = device->newdata.time; #ifdef TIMEHINT_ENABLE diff --git a/ntpshmread.c b/ntpshmread.c index 092e6e95..7a9206e3 100644 --- a/ntpshmread.c +++ b/ntpshmread.c @@ -74,16 +74,7 @@ enum segstat_t shm_query(/*@null@*/struct shmTime *shm_in, /*@out@*/struct shm_s /*@-type@*//* splint is confused about struct timespec */ shm_stat->tvc.tv_sec = shm_stat->tvc.tv_nsec = 0; -#ifdef HAVE_CLOCK_GETTIME clock_gettime(CLOCK_REALTIME, &shm_stat->tvc); -#else - { - struct timeval tv; - (void)gettimeofday(&tv, NULL); - shm_stat->tvc.tv_sec = tv.tv_sec; - shm_stat->tvc.tv_nsec = tv.tv_usec * 1000; - } -#endif /* relying on word access to be atomic here */ if (shm->valid == 0) { diff --git a/ppsthread.c b/ppsthread.c index ad8750a4..b8a716c7 100644 --- a/ppsthread.c +++ b/ppsthread.c @@ -269,9 +269,6 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg) /* the system clock ime, to the nSec, when the last fix received */ /* using a double would cause loss of precision */ struct timespec last_fixtime_clock = {0, 0}; -#ifndef HAVE_CLOCK_GETTIME - struct timeval clock_tv = {0, 0}; -#endif /* HAVE_CLOCK_GETTIME */ struct timespec clock_ts = {0, 0}; time_t last_second_used = 0; #if defined(TIOCMIWAIT) @@ -359,24 +356,12 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg) /*@-noeffect@*/ /* get the time after we just woke up */ -#ifdef HAVE_CLOCK_GETTIME - /* using clock_gettime() here, that is nSec, - * not uSec like gettimeofday */ if ( 0 > clock_gettime(CLOCK_REALTIME, &clock_ts) ) { /* uh, oh, can not get time! */ gpsd_report(&session->context->errout, LOG_ERROR, "PPS clock_gettime() failed\n"); break; } -#else - if ( 0 > gettimeofday(&clock_tv, NULL) ) { - /* uh, oh, can not get time! */ - gpsd_report(&session->context->errout, LOG_ERROR, - "PPS gettimeofday() failed\n"); - break; - } - TVTOTS( &clock_ts, &clock_tv); -#endif /* HAVE_CLOCK_GETTIME */ /*@+noeffect@*/ /* got the edge, got the time just after the edge, now quickly -- cgit v1.2.1