]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/ntp/util/sht.c
MFC r338126: MFV r338092: ntp 4.2.8p12.
[FreeBSD/stable/10.git] / contrib / ntp / util / sht.c
1 /* 
2  * sht.c - Testprogram for shared memory refclock
3  * read/write shared memory segment; see usage
4  */
5 #include "config.h"
6
7 #ifndef SYS_WINNT
8 #include <sys/types.h>
9 #include <sys/ipc.h>
10 #include <sys/shm.h>
11 #include <stdio.h>
12 #include <time.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #else
16 #include <windows.h>
17 #include <time.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <iostream.h>
21 #define sleep(x) Sleep(x*1000)
22 #endif
23 #include <assert.h>
24
25 struct shmTime {
26         int    mode; /* 0 - if valid set
27                       *       use values, 
28                       *       clear valid
29                       * 1 - if valid set 
30                       *       if count before and after read of values is equal,
31                       *         use values 
32                       *       clear valid
33                       */
34         volatile int    count;
35         time_t          clockTimeStampSec;
36         int             clockTimeStampUSec;
37         time_t          receiveTimeStampSec;
38         int             receiveTimeStampUSec;
39         int             leap;
40         int             precision;
41         int             nsamples;
42         volatile int    valid;
43         unsigned        clockTimeStampNSec;     /* Unsigned ns timestamps */
44         unsigned        receiveTimeStampNSec;   /* Unsigned ns timestamps */
45 };
46
47 static struct shmTime *
48 getShmTime (
49         int unit
50         )
51 {
52 #ifndef SYS_WINNT
53         int shmid=shmget (0x4e545030+unit, sizeof (struct shmTime), IPC_CREAT|0777);
54         if (shmid==-1) {
55                 perror ("shmget");
56                 exit (1);
57         }
58         else {
59                 struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
60                 if ((int)(long)p==-1) {
61                         perror ("shmat");
62                         p=0;
63                 }
64                 assert (p!=0);
65                 return p;
66         }
67 #else
68         char buf[10];
69         LPSECURITY_ATTRIBUTES psec=0;
70         snprintf (buf, sizeof(buf), "NTP%d", unit);
71         SECURITY_DESCRIPTOR sd;
72         SECURITY_ATTRIBUTES sa;
73         HANDLE shmid;
74
75         assert (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION));
76         assert (SetSecurityDescriptorDacl(&sd,1,0,0));
77         sa.nLength=sizeof (SECURITY_ATTRIBUTES);
78         sa.lpSecurityDescriptor=&sd;
79         sa.bInheritHandle=0;
80         shmid=CreateFileMapping ((HANDLE)0xffffffff, 0, PAGE_READWRITE,
81                                  psec, sizeof (struct shmTime),buf);
82         if (!shmid) {
83                 shmid=CreateFileMapping ((HANDLE)0xffffffff, 0, PAGE_READWRITE,
84                                          0, sizeof (struct shmTime),buf);
85                 cout <<"CreateFileMapping with psec!=0 failed"<<endl;
86         }
87
88         if (!shmid) {
89                 char mbuf[1000];
90                 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
91                                0, GetLastError (), 0, mbuf, sizeof (mbuf), 0);
92                 int x=GetLastError ();
93                 cout <<"CreateFileMapping "<<buf<<":"<<mbuf<<endl;
94                 exit (1);
95         }
96         else {
97                 struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid, 
98                                                                     FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
99                 if (p==0) {
100                         char mbuf[1000];
101                         FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
102                                        0, GetLastError (), 0, mbuf, sizeof (mbuf), 0);
103                         cout <<"MapViewOfFile "<<buf<<":"<<mbuf<<endl;
104                         exit (1);
105                 }
106                 return p;
107         }
108         return 0;
109 #endif
110 }
111
112
113 int
114 main (
115         int argc,
116         char *argv[]
117         )
118 {
119         volatile struct shmTime *p;
120         int unit;
121         char *argp;
122
123         if (argc<=1) {
124           usage:
125                 printf ("usage: %s [uu:]{r[c][l]|w|snnn}\n",argv[0]);
126                 printf ("       uu use clock unit uu (default: 2)\n");
127                 printf ("       r read shared memory\n");
128                 printf ("       c clear valid-flag\n");
129                 printf ("       l loop (so, rcl will read and clear in a loop\n");
130                 printf ("       w write shared memory with current time\n");
131                 printf ("       snnnn set nsamples to nnn\n");
132                 printf ("       lnnnn set leap to nnn\n");
133                 printf ("       pnnnn set precision to -nnn\n");
134                 exit (0);
135         }
136
137         srand(time(NULL));
138                 
139         unit = strtoul(argv[1], &argp, 10);
140         if (argp == argv[1])
141                 unit = 2;
142         else if (*argp == ':')
143                 argp++;
144         else
145                 goto usage;
146
147         p=getShmTime(unit);
148         switch (*argp) {
149         case 's':
150                 p->nsamples=atoi(argp+1);
151                 break;
152
153         case 'l':
154                 p->leap=atoi(argp+1);
155                 break;
156
157         case 'p':
158                 p->precision=-atoi(argp+1);
159                 break;
160
161         case 'r': {
162                 int clear=0;
163                 int loop=0;
164                 printf ("reader\n");            
165                 while (*++argp) {
166                         switch (*argp) {
167                         case 'l': loop=1; break;
168                         case 'c': clear=1; break;
169                         default : goto usage;
170                         }
171                 }
172 again:
173                 printf ("mode=%d, count=%d, clock=%ld.%09u, rec=%ld.%09u,\n",
174                         p->mode,p->count,
175                         (long)p->clockTimeStampSec,p->clockTimeStampNSec,
176                         (long)p->receiveTimeStampSec,p->receiveTimeStampNSec);
177                 printf ("  leap=%d, precision=%d, nsamples=%d, valid=%d\n",
178                         p->leap, p->precision, p->nsamples, p->valid);
179                 if (!p->valid)
180                         printf ("***\n");
181                 if (clear) {
182                         p->valid=0;
183                         printf ("cleared\n");
184                 }
185                 if (loop) {
186                         sleep (1);
187                         goto again;
188                 }
189                 break;
190         }
191
192         case 'w': {
193                 /* To show some life action, we read the system
194                  * clock and use a bit of fuzz from 'random()' to get a
195                  * bit of wobbling into the values (so we can observe a
196                  * certain jitter!)
197                  */
198                 time_t clk_sec, rcv_sec;
199                 u_int  clk_frc, rcv_frc;
200
201 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
202                 
203                 /* Here we have a high-resolution system clock, and
204                  * we're not afraid to use it!
205                  */
206                 struct timespec tmptime;
207                 if (0 == clock_gettime(CLOCK_REALTIME, &tmptime)) {
208                         rcv_sec = tmptime.tv_sec;
209                         rcv_frc = (u_int)tmptime.tv_nsec;
210                 }
211                 else
212 #endif
213                 {
214                         time(&rcv_sec);
215                         rcv_frc = (u_int)random() % 1000000000u;
216                 }
217                 /* add a wobble of ~3.5msec to the clock time */
218                 clk_sec = rcv_sec;
219                 clk_frc = rcv_frc + (u_int)(random()%7094713 - 3547356);
220                 /* normalise result -- the SHM driver is picky! */
221                 while ((int)clk_frc < 0) {
222                         clk_frc += 1000000000;
223                         clk_sec -= 1;
224                 }
225                 while ((int)clk_frc >= 1000000000) {
226                         clk_frc -= 1000000000;
227                         clk_sec += 1;
228                 }
229                 
230                 /* Most 'real' time sources would create a clock
231                  * (reference) time stamp where the fraction is zero,
232                  * but that's not an actual requirement. So we show how
233                  * to deal with the time stamps in general; changing the
234                  * behaviour for cases where the fraction of the
235                  * clock time is zero should be trivial.
236                  */ 
237                 printf ("writer\n");
238                 p->mode=0;
239                 if (!p->valid) {
240                         p->clockTimeStampSec    = clk_sec;
241                         p->clockTimeStampUSec   = clk_frc / 1000; /* truncate! */
242                         p->clockTimeStampNSec   = clk_frc;
243                         p->receiveTimeStampSec  = rcv_sec;
244                         p->receiveTimeStampUSec = rcv_frc / 1000; /* truncate! */
245                         p->receiveTimeStampNSec = rcv_frc;
246                         printf ("%ld.%09u %ld.%09u\n",
247                                 (long)p->clockTimeStampSec  , p->clockTimeStampNSec  ,
248                                 (long)p->receiveTimeStampSec, p->receiveTimeStampNSec);
249                         p->valid=1;
250                 }
251                 else {
252                         printf ("p->valid still set\n"); /* not an error! */
253                 }
254                 break;
255         }
256         default:
257                 break;
258         }
259         return 0;
260 }