>From 9dd3a35a201b5ea8a4117b458c301c8587dbae51 Mon Sep 17 00:00:00 2001 From: Michael Tatarinov Date: Tue, 5 Nov 2013 15:33:40 +0400 Subject: [PATCH] Refactoring NTPSHM. --- gpsd.c | 20 ++++++-- gpsd.h-tail | 6 +-- ntpshm.c | 158 ++++++++++++++---------------------------------------------- 3 files changed, 54 insertions(+), 130 deletions(-) diff --git a/gpsd.c b/gpsd.c index e787765..50a9cfa 100644 --- a/gpsd.c +++ b/gpsd.c @@ -704,7 +704,7 @@ static bool open_device( /address@hidden@*/struct gps_device_t *device) ntpshm_link_activate(device); gpsd_report(context.debug, LOG_INF, "NTPD ntpshm_link_activate: %d\n", - (int)device->shmindex >= 0); + (int)device->shmIndex >= 0); #endif /* NTPSHM_ENABLE */ gpsd_report(context.debug, LOG_INF, @@ -1530,15 +1530,25 @@ static void all_reports(struct gps_device_t *device, gps_mask_t changed) } else if (!device->ship_to_ntpd) { //gpsd_report(context.debug, LOG_PROG, "NTP: No precision time report\n"); } else { - double offset; + double actual_time, integral, fractional; + struct timespec actual_ts, clock_ts; + + (void)clock_gettime(CLOCK_REALTIME, &clock_ts); + actual_time = device->newdata.time; //gpsd_report(context.debug, LOG_PROG, "NTP: Got one\n"); /* assume zero when there's no offset method */ if (device->device_type == NULL || device->device_type->time_offset == NULL) - offset = 0.0; + actual_time += 0.0; else - offset = device->device_type->time_offset(device); - (void)ntpshm_put(device, device->newdata.time, offset); + actual_time += device->device_type->time_offset(device); + fractional = modf(actual_time, &integral); + actual_ts.tv_sec = (time_t)integral; + actual_ts.tv_nsec = (long)(fractional * 1e+9); + /* setting the precision here does not seem to help anything, too + * hard to calculate properly anyway. Let ntpd figure it out. + * Any NMEA will be about -1 or -2. Garmin GPS-18/USB is around -6 or -7. */ + (void)ntpshm_put(device, device->shmIndex, &actual_ts, &clock_ts, -1); device->last_fixtime = device->newdata.time; } #endif /* NTPSHM_ENABLE */ diff --git a/gpsd.h-tail b/gpsd.h-tail index 831585f..594179f 100644 --- a/gpsd.h-tail +++ b/gpsd.h-tail @@ -466,9 +466,9 @@ struct gps_device_t { unsigned long chars; /* characters in the cycle */ #endif /* TIMING_ENABLE */ #ifdef NTPSHM_ENABLE - int shmindex; bool ship_to_ntpd; - int shmTimeP; + int shmIndex; + int shmIndexPPS; #endif /* NTPSHM_ENABLE */ timestamp_t last_fixtime; /* so updates happen once */ #ifdef PPS_ENABLE @@ -820,7 +820,7 @@ extern unsigned int ais_binary_encode(struct ais_t *ais, /address@hidden@*/unsigned char extern void ntpshm_context_init(struct gps_context_t *); extern void ntpshm_session_init(struct gps_device_t *); -extern int ntpshm_put(struct gps_device_t *, double, double); +extern int ntpshm_put(struct gps_device_t *, int, struct timespec *, struct timespec *, int); extern void ntpshm_link_deactivate(struct gps_device_t *); extern void ntpshm_link_activate(struct gps_device_t *); diff --git a/ntpshm.c b/ntpshm.c index abc5908..a091c26 100644 --- a/ntpshm.c +++ b/ntpshm.c @@ -52,9 +52,9 @@ struct shmTime int precision; int nsamples; int valid; - unsigned clockTimeStampNSec; /* Unsigned ns timestamps */ - unsigned receiveTimeStampNSec; /* Unsigned ns timestamps */ - int dummy[8]; + unsigned clockTimeStampNSec; /* Unsigned ns timestamps */ + unsigned receiveTimeStampNSec; /* Unsigned ns timestamps */ + int pad[8]; }; /* Note: you can start gpsd as non-root, and have it work with ntpd. @@ -214,39 +214,27 @@ void ntpshm_session_init(struct gps_device_t *session) { #ifdef NTPSHM_ENABLE /* mark NTPD shared memory segments as unused */ - session->shmindex = -1; + session->shmIndex = -1; #endif /* NTPSHM_ENABLE */ #ifdef PPS_ENABLE - session->shmTimeP = -1; + session->shmIndexPPS = -1; #endif /* PPS_ENABLE */ } -int ntpshm_put(struct gps_device_t *session, double fixtime, double fudge) -/* put a received fix time into shared memory for NTP */ +/* put time into shared memory for NTP */ +int ntpshm_put(struct gps_device_t *session, + int index, + struct timespec *actual_ts, + struct timespec *clock_ts, + int precision) { /* shmTime is volatile to try to prevent C compiler from reordering * writes, or optimizing some 'dead code'. but CPU cache may still - *write out of order since we do not use memory barriers, yet */ + * write out of order since we do not use memory barriers, yet */ volatile struct shmTime *shmTime = NULL; - struct timeval tv; - double seconds, microseconds; - - // gpsd_report(session->context->debug, LOG_PROG, "NTP: doing ntpshm_put(,%g, %g)\n", fixtime, fudge); - if (session->shmindex < 0 || - (shmTime = session->context->shmTime[session->shmindex]) == NULL) { - gpsd_report(session->context->debug, LOG_RAW, - "NTPD missing shm\n"); - return 0; - } - (void)gettimeofday(&tv, NULL); - fixtime += fudge; - microseconds = 1000000.0 * modf(fixtime, &seconds); - if (shmTime->clockTimeStampSec == (time_t) seconds) { - gpsd_report(session->context->debug, LOG_RAW, - "NTPD ntpshm_put: skipping duplicate second\n"); + if (0 > index || (shmTime = session->context->shmTime[index]) == NULL) return 0; - } /* we use the shmTime mode 1 protocol * @@ -261,110 +249,34 @@ int ntpshm_put(struct gps_device_t *session, double fixtime, double fudge) * use values * clear valid * + * FIXME need a memory barrier here to prevent write reordering by + * the compiler or CPU cache */ shmTime->valid = 0; shmTime->count++; - /* FIXME need a memory barrier here to prevent write reordering by - * the compiler or CPU cache */ - shmTime->clockTimeStampSec = (time_t) seconds; - shmTime->clockTimeStampUSec = (int)microseconds; - shmTime->clockTimeStampNSec = (unsigned)(microseconds*1000); - shmTime->receiveTimeStampSec = (time_t) tv.tv_sec; - shmTime->receiveTimeStampUSec = (int)tv.tv_usec; - shmTime->receiveTimeStampNSec = (int)(tv.tv_usec*1000); + shmTime->clockTimeStampSec = (time_t)actual_ts->tv_sec; + shmTime->clockTimeStampUSec = (int)(actual_ts->tv_nsec / 1000); + shmTime->clockTimeStampNSec = (unsigned)(actual_ts->tv_nsec); + shmTime->receiveTimeStampSec = (time_t)clock_ts->tv_sec; + shmTime->receiveTimeStampUSec = (int)(clock_ts->tv_nsec / 1000); + shmTime->receiveTimeStampNSec = (unsigned)(clock_ts->tv_nsec); shmTime->leap = session->context->leap_notify; - /* setting the precision here does not seem to help anything, too - * hard to calculate properly anyway. Let ntpd figure it out. - * Any NMEA will be about -1 or -2. - * Garmin GPS-18/USB is around -6 or -7. - */ - /* FIXME need a memory barrier here to prevent write reordering by - * the compiler or CPU cache */ + shmTime->precision = precision; shmTime->count++; shmTime->valid = 1; - gpsd_report(session->context->debug, LOG_RAW, - "NTPD ntpshm_put: Clock: %lu.%06lu @ %lu.%06lu, fudge: %0.3f\n", - (unsigned long)seconds, (unsigned long)microseconds, - (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec, fudge); - - return 1; -} - -#ifdef PPS_ENABLE -/address@hidden@*//* splint is confused here */ -/* put NTP shared memory info based on received PPS pulse - * - * good news is that kernel PPS gives us nSec resolution - * bad news is that ntpshm only has uSec resolution - * - * 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 timespec *actual_ts, - struct timespec *clock_ts) -{ - volatile struct shmTime *shmTime = NULL, *shmTimeP = NULL; - struct timeval actual_tv, clock_tv; - int precision; - double offset; - - if (0 > session->shmindex || 0 > session->shmTimeP || - (shmTime = session->context->shmTime[session->shmindex]) == NULL || - (shmTimeP = session->context->shmTime[session->shmTimeP]) == NULL) - return 0; - - /* new ntpd interrace can use uSec andnSec */ - /* do NOT use TSTOTV() since that may round up and we need seconds to - * be the same for uSec and nSec. */ - - /* we use the shmTime mode 1 protocol - * - * ntpd does this: - * - * reads valid. - * IFF valid is 1 - * reads count - * reads values - * reads count - * IFF count unchanged - * use values - * clear valid - * - */ - shmTimeP->valid = 0; - shmTimeP->count++; - shmTimeP->clockTimeStampSec = (time_t)actual_ts->tv_sec; - shmTimeP->clockTimeStampUSec = (int)(actual_ts->tv_nsec/1000); - shmTimeP->clockTimeStampUSec = (unsigned)actual_ts->tv_nsec; - shmTimeP->receiveTimeStampSec = (time_t)clock_ts->tv_sec; - shmTimeP->receiveTimeStampUSec = (int)(clock_ts->tv_nsec/1000); - shmTimeP->receiveTimeStampNSec = (unsigned)clock_ts->tv_nsec; - 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 */ - shmTimeP->precision = -16; - shmTimeP->count++; - shmTimeP->valid = 1; - - /* this is more an offset jitter/dispersion than precision, - * but still useful for debug */ - 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; /address@hidden@*//* 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, + "ntpshm_put %lu.%09lu @ %lu.%09lu\n", + (unsigned long)actual_ts->tv_sec, + (unsigned long)actual_ts->tv_nsec, (unsigned long)clock_ts->tv_sec, - (unsigned long)clock_ts->tv_nsec, - precision); + (unsigned long)clock_ts->tv_nsec); /address@hidden@*/ return 1; } +#if defined(PPS_ENABLE) #define SOCK_MAGIC 0x534f434b struct sock_sample { struct timeval tv; @@ -466,7 +378,9 @@ static /address@hidden@*/ char *report_hook(struct gps_device_t *session, log1 = "accepted chrony sock"; chrony_send(session, &td->real, &td->clock, edge_offset); } - (void)ntpshm_pps(session, &td->real, &td->clock); + /* precision is a placebo, ntpd does not really use it + * real world accuracy is around 16uS, thus -16 precision */ + (void)ntpshm_put(session, session->shmIndexPPS, &td->real, &td->clock, -16); return log1; } @@ -475,11 +389,11 @@ static /address@hidden@*/ char *report_hook(struct gps_device_t *session, void ntpshm_link_deactivate(struct gps_device_t *session) /* release ntpshm storage for a session */ { - (void)ntpshm_free(session->context, session->shmindex); + (void)ntpshm_free(session->context, session->shmIndex); #if defined(PPS_ENABLE) - if (session->shmTimeP != -1) { + if (session->shmIndexPPS != -1) { pps_thread_deactivate(session); - (void)ntpshm_free(session->context, session->shmTimeP); + (void)ntpshm_free(session->context, session->shmIndexPPS); } #endif /* PPS_ENABLE */ } @@ -488,9 +402,9 @@ void ntpshm_link_activate(struct gps_device_t *session) /* set up ntpshm storage for a session */ { /* allocate a shared-memory segment for "NMEA" time data */ - session->shmindex = ntpshm_alloc(session->context); + session->shmIndex = ntpshm_alloc(session->context); - if (0 > session->shmindex) { + if (0 > session->shmIndex) { gpsd_report(session->context->debug, LOG_INF, "NTPD ntpshm_alloc() failed\n"); #if defined(PPS_ENABLE) } else if (session->sourcetype == source_usb || session->sourcetype == source_rs232) { @@ -498,7 +412,7 @@ void ntpshm_link_activate(struct gps_device_t *session) * for the 1pps time data and launch a thread to capture the 1pps * transitions */ - if ((session->shmTimeP = ntpshm_alloc(session->context)) < 0) { + if ((session->shmIndexPPS = ntpshm_alloc(session->context)) < 0) { gpsd_report(session->context->debug, LOG_INF, "NTPD ntpshm_alloc(1) failed\n"); } else { init_hook(session); -- 1.8.3.1