diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | driver_ubx.c | 4 | ||||
-rw-r--r-- | ntpmon.c | 69 | ||||
-rw-r--r-- | ntpmon.xml | 22 | ||||
-rw-r--r-- | ntpshm.h | 2 | ||||
-rw-r--r-- | ntpshmread.c | 9 |
6 files changed, 50 insertions, 57 deletions
@@ -50,6 +50,7 @@ gpsmon.html gpspipe.html gpsprof.html gps2udp.html +ntpmon.html libgps.html libgpsd.html libgpsmm.html diff --git a/driver_ubx.c b/driver_ubx.c index 2f2a7358..ec5876c2 100644 --- a/driver_ubx.c +++ b/driver_ubx.c @@ -228,8 +228,8 @@ ubx_msg_nav_timegps(struct gps_device_t *session, unsigned char *buf, (double)tow / 1000.0); gpsd_report(&session->context->errout, LOG_DATA, - "TIMEGPS: time=%.2f mask={TIME}\n", - session->newdata.time); + "TIMEGPS: time=%.2f leap=%d, mask={TIME}\n", + session->newdata.time, session->context->leap_seconds); return TIME_SET | PPSTIME_IS; } @@ -18,20 +18,6 @@ static struct shmTime *segments[NTPSEGMENTS + 1]; static struct timespec tick[NTPSEGMENTS + 1]; -static int shm_startup(int count) -/* open a specified number of segments */ -{ - int i; - - for (i = 0; i < count; i++) { - segments[i] = shm_get(i, true); - if (segments[i] == NULL) - return i; - } - - return count; -} - static void shm_shutdown(void) /* shut down all active segments */ { @@ -41,32 +27,28 @@ static void shm_shutdown(void) (void)shmdt((void *)(*pp)); } - int main(int argc, char **argv) { int units = 0; - int opened = 0; int option; + int i; + bool verbose = false; -#define USAGE "usage: ntpmon [-n units] [-s]\n" - while ((option = getopt(argc, argv, "hn:s")) != -1) { +#define USAGE "usage: ntpmon [-s]\n" + while ((option = getopt(argc, argv, "hsv")) != -1) { switch (option) { - case 'n': - units = atoi(optarg); - opened = shm_startup(units); - if (opened < units){ - fprintf(stderr, "ntpmon: open of unit %d failed.\n", opened); - exit(EXIT_FAILURE); - } - break; case 's': - if (units > 0) + if (units > 0) { shm_shutdown(); - else { + exit(EXIT_SUCCESS); + } else { fprintf(stderr, "ntpmon: zero units declared.\n"); exit(EXIT_FAILURE); } break; + case 'v': + verbose = true; + break; case 'h': default: fprintf(stderr, USAGE); @@ -74,19 +56,28 @@ int main(int argc, char **argv) } } - (void)printf("ntpmon version 1\nunits %d\n", units); + /* grab all segments, keep the non-null ones */ + for (i = 0; i < NTPSEGMENTS; i++) { + segments[i] = shm_get(i, false, true); + if (verbose && segments[i] != NULL) + fprintf(stderr, "unit %d opened\n", i); + } + if (verbose) + + (void)printf("ntpmon version 1\n%%\n"); for (;;) { struct shm_stat_t shm_stat; int i; - printf("%%\n"); - for (i = 0; i < units; i++) { + for (i = 0; i < NTPSEGMENTS; i++) { enum segstat_t status = shm_query(segments[i], &shm_stat); + if (verbose) + fprintf(stderr, "unit %d status %d\n", i, status); switch(status) { case OK: - if (shm_stat.tvc.tv_sec >= tick[i].tv_sec || shm_stat.tvc.tv_sec >= tick[i].tv_nsec) { + if (shm_stat.tvc.tv_sec != tick[i].tv_nsec || shm_stat.tvc.tv_sec != tick[i].tv_nsec) { printf("sample %s %ld %ld %ld %ld %ld %ld %d %d\n", shm_name(i), shm_stat.tvc.tv_sec, shm_stat.tvc.tv_nsec, @@ -96,6 +87,8 @@ int main(int argc, char **argv) tick[i] = shm_stat.tvc; } break; + case NO_SEGMENT: + break; case NOT_READY: /* do nothing, data not ready, wait another cycle */ break; @@ -112,11 +105,17 @@ int main(int argc, char **argv) break; } } - - sleep(1); + + /* + * Even on a 1 Hz PPS, a sleep(1) may end up + * being sleep(1.1) and missing a beat. Since + * we're ignoring duplicates via timestamp, polling + * at interval < 1 sec shouldn't be a problem. + */ + usleep(1000); } - exit(0); + exit(EXIT_SUCCESS); } /* end */ @@ -23,11 +23,6 @@ BSD terms apply: see the file COPYING in the distribution root for details. <cmdsynopsis> <command>ntpmon</command> <arg choice='opt'>-h </arg> - <group> - <arg choice='plain'>-b</arg> - <arg choice='plain'>-n</arg> - </group> - <arg choice='opt'>-n <replaceable>units</replaceable></arg> <arg choice='opt'>-s </arg> </cmdsynopsis> </refsynopsisdiv> @@ -41,15 +36,14 @@ ntpd, the Network Time Protocol daemon. It reads these in exactly the way an ntpd instance does. It can be run concurrently with ntpd without interfering with ntpd's normal operation.</para> -<para>This program runs forever or until interrupted, generating -sample reports to standard output once per second. Each line -consists of whitespace-separated textual fields.</para> +<para>This program runs forever or until interrupted, generating +sample reports to standard output. Each line consists of +whitespace-separated textual fields.</para> <para>Here is an example of the beginning of a report file: <literallayout> ntpmon version 1 -units 4 % sample NTP2 1424865634 779678109 1424865634 109814469 1424865634 0 0 -1 sample NTP3 1424865634 779693823 1424865633 999315444 1424865634 0 0 -20 @@ -63,14 +57,8 @@ sample NTP3 1424865635 779916521 1424865634 999344705 1424865635 0 0 -20 version of the output format; the version line begins with "ntpmon version" and is followed by a numeric version field.</para> -<para>The header line is followed by a "units" line in which the -second field is the number of NTP units (starting from NTP0 -consecutively upwards) sampled on each cycle.</para> - -<para>The remainder of the file is a list of stanzas each led by a line -containing the single field "%%". Each stanza consists of sample lines.</para> - -<para>The fields of a sample line are as follows: +<para>The remainder of the file is sample lines. The fields of a +sample line are as follows: <orderedlist> <listitem><para>The keyword "sample"</para></listitem> @@ -58,7 +58,7 @@ struct shm_stat_t { int leap; }; -struct shmTime *shm_get(int, bool); +struct shmTime *shm_get(int, bool, bool); extern char *shm_name(const int); enum segstat_t shm_query(struct shmTime *, struct shm_stat_t *); diff --git a/ntpshmread.c b/ntpshmread.c index 5854df64..710dfd33 100644 --- a/ntpshmread.c +++ b/ntpshmread.c @@ -18,7 +18,7 @@ #include "ntpshm.h" -struct shmTime *shm_get(int unit, bool forall) +struct shmTime *shm_get(const int unit, const bool create, const bool forall) /* initialize an initial segment */ { struct shmTime *p = NULL; @@ -29,7 +29,7 @@ struct shmTime *shm_get(int unit, bool forall) * as long as everybody does it the same way. */ shmid = shmget(NTPD_BASE + unit, sizeof(struct shmTime), - IPC_CREAT | (forall ? 0666 : 0600)); + (create ? IPC_CREAT : 0) | (forall ? 0666 : 0600)); if (shmid == -1) { /* error */ return NULL; } @@ -144,6 +144,11 @@ enum segstat_t shm_query(struct shmTime *shm_in, struct shm_stat_t *shm_stat) } shm->valid = 0; + /* + * leap field is not a leap offset but a leap notification code. + * The values are magic numbers used by NTP and set by GPSD, if at all, in + * the subframe code. + */ shm_stat->leap = shm->leap; shm_stat->precision = shm->precision; shm_stat->mode = OK; |