aboutsummaryrefslogtreecommitdiff
path: root/util/sht.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/sht.c')
-rw-r--r--util/sht.c221
1 files changed, 148 insertions, 73 deletions
diff --git a/util/sht.c b/util/sht.c
index b993de907d08..dfd97ffb9f1f 100644
--- a/util/sht.c
+++ b/util/sht.c
@@ -2,6 +2,8 @@
* sht.c - Testprogram for shared memory refclock
* read/write shared memory segment; see usage
*/
+#include "config.h"
+
#ifndef SYS_WINNT
#include <sys/types.h>
#include <sys/ipc.h>
@@ -19,6 +21,7 @@
#define sleep(x) Sleep(x*1000)
#endif
#include <assert.h>
+
struct shmTime {
int mode; /* 0 - if valid set
* use values,
@@ -28,18 +31,20 @@ struct shmTime {
* use values
* clear valid
*/
- int count;
- time_t clockTimeStampSec;
- int clockTimeStampUSec;
- time_t receiveTimeStampSec;
- int receiveTimeStampUSec;
- int leap;
- int precision;
- int nsamples;
- int valid;
+ volatile int count;
+ time_t clockTimeStampSec;
+ int clockTimeStampUSec;
+ time_t receiveTimeStampSec;
+ int receiveTimeStampUSec;
+ int leap;
+ int precision;
+ int nsamples;
+ volatile int valid;
+ unsigned clockTimeStampNSec; /* Unsigned ns timestamps */
+ unsigned receiveTimeStampNSec; /* Unsigned ns timestamps */
};
-struct shmTime *
+static struct shmTime *
getShmTime (
int unit
)
@@ -62,7 +67,7 @@ getShmTime (
#else
char buf[10];
LPSECURITY_ATTRIBUTES psec=0;
- sprintf (buf,"NTP%d",unit);
+ snprintf (buf, sizeof(buf), "NTP%d", unit);
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
HANDLE shmid;
@@ -111,75 +116,145 @@ main (
char *argv[]
)
{
- volatile struct shmTime *p=getShmTime(2);
+ volatile struct shmTime *p;
+ int unit;
+ char *argp;
+
if (argc<=1) {
- printf ("usage: %s r[c][l]|w|snnn\n",argv[0]);
+ usage:
+ printf ("usage: %s [uu:]{r[c][l]|w|snnn}\n",argv[0]);
+ printf (" uu use clock unit uu (default: 2)\n");
printf (" r read shared memory\n");
- printf (" c clear valid-flag\n");
- printf (" l loop (so, rcl will read and clear in a loop\n");
+ printf (" c clear valid-flag\n");
+ printf (" l loop (so, rcl will read and clear in a loop\n");
printf (" w write shared memory with current time\n");
printf (" snnnn set nsamples to nnn\n");
printf (" lnnnn set leap to nnn\n");
printf (" pnnnn set precision to -nnn\n");
exit (0);
}
- switch (argv[1][0]) {
- case 's': {
- p->nsamples=atoi(&argv[1][1]);
- }
- break;
- case 'l': {
- p->leap=atoi(&argv[1][1]);
- }
- break;
- case 'p': {
- p->precision=-atoi(&argv[1][1]);
- }
- break;
- case 'r': {
- char *ap=&argv[1][1];
- int clear=0;
- int loop=0;
- printf ("reader\n");
- while (*ap) {
- switch (*ap) {
- case 'l' : loop=1; break;
- case 'c' : clear=1; break;
- }
- ap++;
- }
- do {
- printf ("mode=%d, count=%d, clock=%d.%d, rec=%d.%d,\n",
- p->mode,p->count,p->clockTimeStampSec,p->clockTimeStampUSec,
- p->receiveTimeStampSec,p->receiveTimeStampUSec);
- printf (" leap=%d, precision=%d, nsamples=%d, valid=%d\n",
- p->leap, p->precision, p->nsamples, p->valid);
- if (!p->valid)
- printf ("***\n");
- if (clear) {
- p->valid=0;
- printf ("cleared\n");
- }
- if (loop)
- sleep (1);
- } while (loop);
- }
- break;
- case 'w': {
- printf ("writer\n");
- p->mode=0;
- if (!p->valid) {
- p->clockTimeStampSec=time(0)-20;
- p->clockTimeStampUSec=0;
- p->receiveTimeStampSec=time(0)-1;
- p->receiveTimeStampUSec=0;
- printf ("%d %d\n",p->clockTimeStampSec, p->receiveTimeStampSec);
- p->valid=1;
- }
- else {
- printf ("p->valid still set\n"); /* not an error! */
- }
- }
- break;
+
+ srand(time(NULL));
+
+ unit = strtoul(argv[1], &argp, 10);
+ if (argp == argv[1])
+ unit = 2;
+ else if (*argp == ':')
+ argp++;
+ else
+ goto usage;
+
+ p=getShmTime(unit);
+ switch (*argp) {
+ case 's':
+ p->nsamples=atoi(argp+1);
+ break;
+
+ case 'l':
+ p->leap=atoi(argp+1);
+ break;
+
+ case 'p':
+ p->precision=-atoi(argp+1);
+ break;
+
+ case 'r': {
+ int clear=0;
+ int loop=0;
+ printf ("reader\n");
+ while (*++argp) {
+ switch (*argp) {
+ case 'l': loop=1; break;
+ case 'c': clear=1; break;
+ default : goto usage;
+ }
+ }
+again:
+ printf ("mode=%d, count=%d, clock=%ld.%09u, rec=%ld.%09u,\n",
+ p->mode,p->count,
+ (long)p->clockTimeStampSec,p->clockTimeStampNSec,
+ (long)p->receiveTimeStampSec,p->receiveTimeStampNSec);
+ printf (" leap=%d, precision=%d, nsamples=%d, valid=%d\n",
+ p->leap, p->precision, p->nsamples, p->valid);
+ if (!p->valid)
+ printf ("***\n");
+ if (clear) {
+ p->valid=0;
+ printf ("cleared\n");
+ }
+ if (loop) {
+ sleep (1);
+ goto again;
+ }
+ break;
}
+
+ case 'w': {
+ /* To show some life action, we read the system
+ * clock and use a bit of fuzz from 'random()' to get a
+ * bit of wobbling into the values (so we can observe a
+ * certain jitter!)
+ */
+ time_t clk_sec, rcv_sec;
+ uint clk_frc, rcv_frc;
+
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
+
+ /* Here we have a high-resolution system clock, and
+ * we're not afraid to use it!
+ */
+ struct timespec tmptime;
+ if (0 == clock_gettime(CLOCK_REALTIME, &tmptime)) {
+ rcv_sec = tmptime.tv_sec;
+ rcv_frc = (uint)tmptime.tv_nsec;
+ }
+ else
+#endif
+ {
+ time(&rcv_sec);
+ rcv_frc = (uint)random() % 1000000000u;
+ }
+ /* add a wobble of ~3.5msec to the clock time */
+ clk_sec = rcv_sec;
+ clk_frc = rcv_frc + (uint)(random()%7094713 - 3547356);
+ /* normalise result -- the SHM driver is picky! */
+ while ((int)clk_frc < 0) {
+ clk_frc += 1000000000;
+ clk_sec -= 1;
+ }
+ while ((int)clk_frc >= 1000000000) {
+ clk_frc -= 1000000000;
+ clk_sec += 1;
+ }
+
+ /* Most 'real' time sources would create a clock
+ * (reference) time stamp where the fraction is zero,
+ * but that's not an actual requirement. So we show how
+ * to deal with the time stamps in general; changing the
+ * behaviour for cases where the fraction of the
+ * clock time is zero should be trivial.
+ */
+ printf ("writer\n");
+ p->mode=0;
+ if (!p->valid) {
+ p->clockTimeStampSec = clk_sec;
+ p->clockTimeStampUSec = clk_frc / 1000; /* truncate! */
+ p->clockTimeStampNSec = clk_frc;
+ p->receiveTimeStampSec = rcv_sec;
+ p->receiveTimeStampUSec = rcv_frc / 1000; /* truncate! */
+ p->receiveTimeStampNSec = rcv_frc;
+ printf ("%ld.%09u %ld.%09u\n",
+ (long)p->clockTimeStampSec , p->clockTimeStampNSec ,
+ (long)p->receiveTimeStampSec, p->receiveTimeStampNSec);
+ p->valid=1;
+ }
+ else {
+ printf ("p->valid still set\n"); /* not an error! */
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
}