From 3f49461c5fd50436fe133adc7a8121144305ad64 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 3 Nov 2013 09:15:55 -0500 Subject: Use timedrift_t for all hook arguments. No logic changes in this commit. We push naosecond precision closer to where time hints are shipped. Changes to ppsthread.c are kept minimal; it needs a cleanup but that will be done in another change that can be separately reviewed. All regression tests pass. PPS is live in gpsmon and reported by gpsd. --- gpsd.c | 9 +++++---- gpsd.h-tail | 5 ++--- gpsmon.c | 8 +++----- ntpshm.c | 54 ++++++++++++++++++++++++++++-------------------------- ppsthread.c | 9 +++++++-- 5 files changed, 45 insertions(+), 40 deletions(-) diff --git a/gpsd.c b/gpsd.c index c6573265..e787765f 100644 --- a/gpsd.c +++ b/gpsd.c @@ -1658,8 +1658,8 @@ static int handle_gpsd_request(struct subscriber_t *sub, const char *buf) #ifdef PPS_ENABLE static void ship_pps_drift_message(struct gps_device_t *session, - unsigned long sec, - struct timespec *ts) + struct timedrift_t *td, + double edge_offset UNUSED) /* on PPS interrupt, ship a drift message to all clients */ { #ifdef SOCKET_EXPORT_ENABLE @@ -1668,9 +1668,10 @@ static void ship_pps_drift_message(struct gps_device_t *session, * Yes, real_nsec is constant 0 because our "real time" is top of GPS * second. This will change when we support 5Hz devices fully. */ - notify_watchers(session, "{\"class\":\"PPS\",\"device\":\"%s\",\"real_sec\":%ld, \"real_nsec\":0,\"clock_sec\":%ld,\"clock_nsec\":%ld}\r\n", + notify_watchers(session, "{\"class\":\"PPS\",\"device\":\"%s\",\"real_sec\":%ld, \"real_nsec\":%ld,\"clock_sec\":%ld,\"clock_nsec\":%ld}\r\n", session->gpsdata.dev.path, - sec, ts->tv_sec, ts->tv_nsec); + td->real.tv_sec, td->real.tv_nsec, + td->clock.tv_sec, td->clock.tv_nsec); /*@+type@*/ #endif /* SOCKET_EXPORT_ENABLE */ } diff --git a/gpsd.h-tail b/gpsd.h-tail index c36e7816..831585fe 100644 --- a/gpsd.h-tail +++ b/gpsd.h-tail @@ -257,7 +257,7 @@ struct gps_context_t { #endif /* NTPSHM_ENABLE */ #ifdef PPS_ENABLE /*@null@*/ void (*pps_hook)(struct gps_device_t *, - unsigned long, struct timespec *); + struct timedrift_t *, double); #endif /* PPS_ENABLE */ #ifdef SHM_EXPORT_ENABLE /* we don't want the compiler to treat writes to shmexport as dead code, @@ -477,8 +477,7 @@ struct gps_device_t { #endif /* defined(HAVE_SYS_TIMEPPS_H) */ int chronyfd; /* for talking to chrony */ /*@null@*/ char *(*thread_report_hook)(struct gps_device_t *, - struct timeval *, - struct timespec *, + struct timedrift_t *, double); /*@null@*/ void (*thread_wrap_hook)(struct gps_device_t *); #endif /* PPS_ENABLE */ diff --git a/gpsmon.c b/gpsmon.c index f90cf934..53865a8b 100644 --- a/gpsmon.c +++ b/gpsmon.c @@ -838,9 +838,8 @@ static void gpsmon_hook(struct gps_device_t *device, gps_mask_t changed UNUSED) #ifdef PPS_ENABLE static char *pps_report(struct gps_device_t *session UNUSED, - struct timeval *pps_tv, - struct timespec *sysclock_ts, - double edge_offset UNUSED) { + struct timedrift_t *td UNUSED, + double edge_offset) { /* * Ugh. Access through a shared global is nasty. * This may be a layer violation that needs to be fixed. @@ -848,8 +847,7 @@ static char *pps_report(struct gps_device_t *session UNUSED, * Read access to timedelta is not thread-locked. * Instead we're relying on access to floats to be atomic. */ - timedelta = (pps_tv->tv_sec + pps_tv->tv_usec / 1e6) - - (sysclock_ts->tv_sec + sysclock_ts->tv_nsec / 1e9); + timedelta = edge_offset; packet_log("-------------------------------------" " PPS " "-------------------------------------\n"); diff --git a/ntpshm.c b/ntpshm.c index 0388a117..4322e4db 100644 --- a/ntpshm.c +++ b/ntpshm.c @@ -294,14 +294,15 @@ int ntpshm_put(struct gps_device_t *session, double fixtime, double fudge) * good news is that kernel PPS gives us nSec resolution * bad news is that ntpshm only has uSec resolution * - * actual_tv is the actual time we think the PPS happened - * ts is the time we saw the pulse + * actual_ts is the actual time we think the PPS happened + * clock_ts is the time we saw the pulse */ -static int ntpshm_pps(struct gps_device_t *session, struct timeval *actual_tv, - struct timespec *ts) +static int ntpshm_pps(struct gps_device_t *session, + struct timespec *actual_ts, + struct timespec *clock_ts) { volatile struct shmTime *shmTime = NULL, *shmTimeP = NULL; - struct timeval tv; + struct timeval actual_tv, clock_tv; int precision; double offset; @@ -312,7 +313,8 @@ static int ntpshm_pps(struct gps_device_t *session, struct timeval *actual_tv, /* for now we use uSec, not nSec */ /*@-type@*//* splint is confused about struct timespec */ - TSTOTV( &tv, ts ); + TSTOTV( &actual_tv, actual_ts ); + TSTOTV( &clock_tv, clock_ts ); /*@+type@*/ /* we use the shmTime mode 1 protocol @@ -331,10 +333,10 @@ static int ntpshm_pps(struct gps_device_t *session, struct timeval *actual_tv, */ shmTimeP->valid = 0; shmTimeP->count++; - shmTimeP->clockTimeStampSec = (time_t)actual_tv->tv_sec; - shmTimeP->clockTimeStampUSec = (int)actual_tv->tv_usec; - shmTimeP->receiveTimeStampSec = (time_t)tv.tv_sec; - shmTimeP->receiveTimeStampUSec = (int)tv.tv_usec; + shmTimeP->clockTimeStampSec = (time_t)actual_tv.tv_sec; + shmTimeP->clockTimeStampUSec = (int)actual_tv.tv_usec; + shmTimeP->receiveTimeStampSec = (time_t)clock_tv.tv_sec; + shmTimeP->receiveTimeStampUSec = (int)clock_tv.tv_usec; shmTimeP->leap = session->context->leap_notify; /* precision is a placebo, ntpd does not really use it * real world accuracy is around 16uS, thus -16 precision */ @@ -344,15 +346,16 @@ static int ntpshm_pps(struct gps_device_t *session, struct timeval *actual_tv, /* this is more an offset jitter/dispersion than precision, * but still useful for debug */ - offset = fabs((double)(tv.tv_sec - actual_tv->tv_sec) - + ((double)(tv.tv_usec - actual_tv->tv_usec) / 1000000.0)); + offset = fabs((double)(clock_tv.tv_sec - actual_tv.tv_sec) + + ((double)(clock_tv.tv_usec - actual_tv.tv_usec) / 1000000.0)); precision = offset != 0 ? (int)(ceil(log(offset) / M_LN2)) : -20; /*@-type@*//* splint is confused about struct timespec */ gpsd_report(session->context->debug, LOG_RAW, "PPS ntpshm_pps %lu.%03lu @ %lu.%09lu, preci %d\n", - (unsigned long)actual_tv->tv_sec, - (unsigned long)actual_tv->tv_usec, - (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec, + (unsigned long)actual_tv.tv_sec, + (unsigned long)actual_tv.tv_usec, + (unsigned long)clock_ts->tv_sec, + (unsigned long)clock_ts->tv_nsec, precision); /*@+type@*/ return 1; @@ -406,12 +409,12 @@ static void init_hook(struct gps_device_t *session) /*@+mustfreefresh@*/ -/* actual_tv is when we think the PPS pulse wass */ -/* ts is the local clocke time we saw the pulse */ -/* offset is actual_tv - tv */ +/* actual_ts is when we think the PPS pulse wass */ +/* clock_ts is the local clocke time we saw the pulse */ +/* offset is actual_ts - clock_ts */ static void chrony_send(struct gps_device_t *session, - struct timeval *actual_tv, - struct timespec *ts UNUSED, double offset) + struct timespec *actual_ts, + struct timespec *clock_ts UNUSED, double offset) { struct sock_sample sample; @@ -420,7 +423,7 @@ static void chrony_send(struct gps_device_t *session, sample.pulse = 0; sample.leap = session->context->leap_notify; sample.magic = SOCK_MAGIC; - sample.tv = *actual_tv; /* structure copy */ + TSTOTV(&sample.tv, actual_ts); sample.offset = offset; (void)send(session->chronyfd, &sample, sizeof (sample), 0); @@ -433,9 +436,8 @@ static void wrap_hook(struct gps_device_t *session) } static /*@observer@*/ char *report_hook(struct gps_device_t *session, - struct timeval *actual_tv, - struct timespec *ts, - double edge_offset) + struct timedrift_t *td, + double edge_offset) /* ship the time of a PPS event to ntpd and/or chrony */ { char *log1; @@ -458,9 +460,9 @@ static /*@observer@*/ char *report_hook(struct gps_device_t *session, log1 = "accepted"; if ( 0 <= session->chronyfd ) { log1 = "accepted chrony sock"; - chrony_send(session, actual_tv, ts, edge_offset); + chrony_send(session, &td->real, &td->clock, edge_offset); } - (void)ntpshm_pps(session, actual_tv, ts); + (void)ntpshm_pps(session, &td->real, &td->clock); return log1; } diff --git a/ppsthread.c b/ppsthread.c index bbaae795..88e1e134 100644 --- a/ppsthread.c +++ b/ppsthread.c @@ -486,14 +486,19 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg) (long)l_offset); log1 = "timestamp out of range"; } else { + struct timedrift_t drift; + drift.real.tv_sec = actual_tv.tv_sec; + drift.real.tv_nsec = 0; + drift.clock = ts; last_second_used = session->last_fixtime; if (session->thread_report_hook != NULL) log1 = session->thread_report_hook(session, - &actual_tv, &ts, edge_offset); + &drift, edge_offset); else log1 = "no report hook"; if (session->context->pps_hook != NULL) - session->context->pps_hook(session, actual_tv.tv_sec, &ts); + session->context->pps_hook(session, + &drift, edge_offset); } gpsd_report(session->context->debug, LOG_RAW, "PPS edge %.20s %lu.%06lu offset %.9f\n", -- cgit v1.2.1