summaryrefslogtreecommitdiff
path: root/ntpshmmon.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2015-02-27 16:45:48 -0500
committerEric S. Raymond <esr@thyrsus.com>2015-02-27 16:45:48 -0500
commita77979ac7b33d5069352794f48effb2ab50554e4 (patch)
tree26b71ebac7889db247cd704c1f8accc54336b574 /ntpshmmon.c
parentc745ecb33358cc8747381f82ce86e22f96b480a0 (diff)
downloadgpsd-a77979ac7b33d5069352794f48effb2ab50554e4.tar.gz
ntpshm.c -> ntpshmwrite.c; ntpmon -> ntpshmmon.
All regression tests pass.
Diffstat (limited to 'ntpshmmon.c')
-rw-r--r--ntpshmmon.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/ntpshmmon.c b/ntpshmmon.c
new file mode 100644
index 00000000..044f9268
--- /dev/null
+++ b/ntpshmmon.c
@@ -0,0 +1,127 @@
+/* ntpshmmon.c -- monitor the inner end of an ntpshmwrite.connection
+ *
+ * This file is Copyright (c) 2010 by the GPSD project
+ * BSD terms apply: see the file COPYING in the distribution root for details.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#ifndef S_SPLINT_S
+#include <unistd.h>
+#endif /* S_SPLINT_S */
+
+#include "ntpshm.h"
+
+#define NTPSEGMENTS 256 /* NTPx for x any byte */
+
+static struct shmTime *segments[NTPSEGMENTS + 1];
+static struct timespec tick[NTPSEGMENTS + 1];
+
+static void shm_shutdown(void)
+/* shut down all active segments */
+{
+ struct shmTime **pp;
+
+ for (pp = segments; pp < segments + NTPSEGMENTS; pp++)
+ if (*pp != NULL)
+ (void)shmdt((void *)(*pp));
+}
+
+int main(int argc, char **argv)
+{
+ int units = 0;
+ int option;
+ int i;
+ bool verbose = false;
+
+#define USAGE "usage: ntpshmmon [-s] [-v] [-h]\n"
+ while ((option = getopt(argc, argv, "hsv")) != -1) {
+ switch (option) {
+ case 's':
+ if (units > 0) {
+ shm_shutdown();
+ exit(EXIT_SUCCESS);
+ } else {
+ fprintf(stderr, "ntpshmmon: zero units declared.\n");
+ exit(EXIT_FAILURE);
+ }
+ //0break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'h':
+ default:
+ fprintf(stderr, USAGE);
+ break;
+ }
+ }
+
+ /* 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);
+ }
+ (void)printf("ntpshmmon version 1\n");
+
+ for (;;) {
+ struct shm_stat_t shm_stat;
+
+ 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:
+ /*@-mustfreefresh -formattype@*/
+ /*@-type@*//* splint is confused about struct timespec */
+ if (shm_stat.tvc.tv_sec != tick[i].tv_sec || shm_stat.tvc.tv_nsec != tick[i].tv_nsec) {
+ printf("sample %s %ld.%09ld %ld.%09ld %ld.%09ld %d %3d\n",
+ shm_name(i),
+ shm_stat.tvc.tv_sec, shm_stat.tvc.tv_nsec,
+ shm_stat.tvr.tv_sec, shm_stat.tvr.tv_nsec,
+ shm_stat.tvt.tv_sec, shm_stat.tvt.tv_nsec,
+ shm_stat.leap, shm_stat.precision);
+ tick[i] = shm_stat.tvc;
+ }
+ /*@+type@*/
+ /*@+mustfreefresh +formattype@*/
+ break;
+ case NO_SEGMENT:
+ break;
+ case NOT_READY:
+ /* do nothing, data not ready, wait another cycle */
+ break;
+ case BAD_MODE:
+ /*@-mustfreefresh@*/
+ fprintf(stderr, "ntpshmmon: unknown mode %d on segment %s\n",
+ shm_stat.status, shm_name(i));
+ /*@+mustfreefresh@*/
+ break;
+ case CLASH:
+ /* do nothing, data is corrupt, wait another cycle */
+ break;
+ default:
+ /*@-mustfreefresh@*/
+ fprintf(stderr, "ntpshmmon: unknown status %d on segment %s\n",
+ status, shm_name(i));
+ /*@+mustfreefresh@*/
+ break;
+ }
+ }
+
+ /*
+ * 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.
+ */
+ (void)usleep(1000);
+ }
+
+ //exit(EXIT_SUCCESS);
+}
+
+/* end */