aboutsummaryrefslogtreecommitdiff
path: root/util/sht.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/sht.c')
-rw-r--r--util/sht.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/util/sht.c b/util/sht.c
new file mode 100644
index 000000000000..dfd97ffb9f1f
--- /dev/null
+++ b/util/sht.c
@@ -0,0 +1,260 @@
+/*
+ * 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>
+#include <sys/shm.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#else
+#include <windows.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream.h>
+#define sleep(x) Sleep(x*1000)
+#endif
+#include <assert.h>
+
+struct shmTime {
+ int mode; /* 0 - if valid set
+ * use values,
+ * clear valid
+ * 1 - if valid set
+ * if count before and after read of values is equal,
+ * use values
+ * clear 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 */
+};
+
+static struct shmTime *
+getShmTime (
+ int unit
+ )
+{
+#ifndef SYS_WINNT
+ int shmid=shmget (0x4e545030+unit, sizeof (struct shmTime), IPC_CREAT|0777);
+ if (shmid==-1) {
+ perror ("shmget");
+ exit (1);
+ }
+ else {
+ struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
+ if ((int)(long)p==-1) {
+ perror ("shmat");
+ p=0;
+ }
+ assert (p!=0);
+ return p;
+ }
+#else
+ char buf[10];
+ LPSECURITY_ATTRIBUTES psec=0;
+ snprintf (buf, sizeof(buf), "NTP%d", unit);
+ SECURITY_DESCRIPTOR sd;
+ SECURITY_ATTRIBUTES sa;
+ HANDLE shmid;
+
+ assert (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION));
+ assert (SetSecurityDescriptorDacl(&sd,1,0,0));
+ sa.nLength=sizeof (SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor=&sd;
+ sa.bInheritHandle=0;
+ shmid=CreateFileMapping ((HANDLE)0xffffffff, 0, PAGE_READWRITE,
+ psec, sizeof (struct shmTime),buf);
+ if (!shmid) {
+ shmid=CreateFileMapping ((HANDLE)0xffffffff, 0, PAGE_READWRITE,
+ 0, sizeof (struct shmTime),buf);
+ cout <<"CreateFileMapping with psec!=0 failed"<<endl;
+ }
+
+ if (!shmid) {
+ char mbuf[1000];
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, GetLastError (), 0, mbuf, sizeof (mbuf), 0);
+ int x=GetLastError ();
+ cout <<"CreateFileMapping "<<buf<<":"<<mbuf<<endl;
+ exit (1);
+ }
+ else {
+ struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
+ FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
+ if (p==0) {
+ char mbuf[1000];
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, GetLastError (), 0, mbuf, sizeof (mbuf), 0);
+ cout <<"MapViewOfFile "<<buf<<":"<<mbuf<<endl;
+ exit (1);
+ }
+ return p;
+ }
+ return 0;
+#endif
+}
+
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ volatile struct shmTime *p;
+ int unit;
+ char *argp;
+
+ if (argc<=1) {
+ 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 (" 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);
+ }
+
+ 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;
+}