Annotation of embedaddon/ntp/ntpd/refclock_shm.c, revision 1.1.1.1
1.1 misho 1: /*
2: * refclock_shm - clock driver for utc via shared memory
3: * - under construction -
4: * To add new modes: Extend or union the shmTime-struct. Do not
5: * extend/shrink size, because otherwise existing implementations
6: * will specify wrong size of shared memory-segment
7: * PB 18.3.97
8: */
9:
10: #ifdef HAVE_CONFIG_H
11: # include <config.h>
12: #endif
13:
14: #if defined(REFCLOCK) && defined(CLOCK_SHM)
15:
16: #include "ntpd.h"
17: #undef fileno
18: #include "ntp_io.h"
19: #undef fileno
20: #include "ntp_refclock.h"
21: #undef fileno
22: #include "ntp_unixtime.h"
23: #undef fileno
24: #include "ntp_stdlib.h"
25:
26: #undef fileno
27: #include <ctype.h>
28: #undef fileno
29:
30: #ifndef SYS_WINNT
31: # include <sys/ipc.h>
32: # include <sys/shm.h>
33: # include <assert.h>
34: # include <unistd.h>
35: # include <stdio.h>
36: #endif
37:
38: /*
39: * This driver supports a reference clock attached thru shared memory
40: */
41:
42: /* Temp hack to simplify testing of the old mode. */
43: #define OLDWAY 0
44:
45: /*
46: * SHM interface definitions
47: */
48: #define PRECISION (-1) /* precision assumed (0.5 s) */
49: #define REFID "SHM" /* reference ID */
50: #define DESCRIPTION "SHM/Shared memory interface"
51:
52: #define NSAMPLES 3 /* stages of median filter */
53:
54: /*
55: * Function prototypes
56: */
57: static int shm_start (int unit, struct peer *peer);
58: static void shm_shutdown (int unit, struct peer *peer);
59: static void shm_poll (int unit, struct peer *peer);
60: static void shm_timer (int unit, struct peer *peer);
61: int shm_peek (int unit, struct peer *peer);
62: void shm_clockstats (int unit, struct peer *peer);
63:
64: /*
65: * Transfer vector
66: */
67: struct refclock refclock_shm = {
68: shm_start, /* start up driver */
69: shm_shutdown, /* shut down driver */
70: shm_poll, /* transmit poll message */
71: noentry, /* not used: control */
72: noentry, /* not used: init */
73: noentry, /* not used: buginfo */
74: shm_timer, /* once per second */
75: };
76:
77: struct shmTime {
78: int mode; /* 0 - if valid set
79: * use values,
80: * clear valid
81: * 1 - if valid set
82: * if count before and after read of values is equal,
83: * use values
84: * clear valid
85: */
86: int count;
87: time_t clockTimeStampSec;
88: int clockTimeStampUSec;
89: time_t receiveTimeStampSec;
90: int receiveTimeStampUSec;
91: int leap;
92: int precision;
93: int nsamples;
94: int valid;
95: int dummy[10];
96: };
97:
98: struct shmunit {
99: struct shmTime *shm; /* pointer to shared memory segment */
100:
101: /* debugging/monitoring counters - reset when printed */
102: int ticks; /* number of attempts to read data*/
103: int good; /* number of valid samples */
104: int notready; /* number of peeks without data ready */
105: int bad; /* number of invalid samples */
106: int clash; /* number of access clashes while reading */
107: };
108:
109:
110: struct shmTime *getShmTime(int);
111:
112: struct shmTime *getShmTime (int unit) {
113: #ifndef SYS_WINNT
114: int shmid=0;
115:
116: /* 0x4e545030 is NTP0.
117: * Big units will give non-ascii but that's OK
118: * as long as everybody does it the same way.
119: */
120: shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
121: IPC_CREAT|(unit<2?0600:0666));
122: if (shmid==-1) { /*error */
123: msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
124: return 0;
125: }
126: else { /* no error */
127: struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
128: if ((int)(long)p==-1) { /* error */
129: msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
130: return 0;
131: }
132: return p;
133: }
134: #else
135: char buf[10];
136: LPSECURITY_ATTRIBUTES psec=0;
137: HANDLE shmid=0;
138: SECURITY_DESCRIPTOR sd;
139: SECURITY_ATTRIBUTES sa;
140: snprintf(buf, sizeof(buf), "NTP%d", unit);
141: if (unit >= 2) { /* world access */
142: if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
143: msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
144: return 0;
145: }
146: if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
147: msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
148: return 0;
149: }
150: sa.nLength=sizeof (SECURITY_ATTRIBUTES);
151: sa.lpSecurityDescriptor=&sd;
152: sa.bInheritHandle=0;
153: psec=&sa;
154: }
155: shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
156: 0, sizeof (struct shmTime),buf);
157: if (!shmid) { /*error*/
158: char buf[1000];
159: FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
160: 0, GetLastError (), 0, buf, sizeof (buf), 0);
161: msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
162: return 0;
163: }
164: else {
165: struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
166: FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
167: if (p==0) { /*error*/
168: char buf[1000];
169: FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
170: 0, GetLastError (), 0, buf, sizeof (buf), 0);
171: msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
172: return 0;
173: }
174: return p;
175: }
176: #endif
177: }
178: /*
179: * shm_start - attach to shared memory
180: */
181: static int
182: shm_start(
183: int unit,
184: struct peer *peer
185: )
186: {
187: struct refclockproc *pp;
188: struct shmunit *up;
189:
190: pp = peer->procptr;
191: pp->io.clock_recv = noentry;
192: pp->io.srcclock = (caddr_t)peer;
193: pp->io.datalen = 0;
194: pp->io.fd = -1;
195:
196: up = emalloc(sizeof(*up));
197: memset(up, 0, sizeof(*up));
198: pp->unitptr = (caddr_t)up;
199:
200: up->shm = getShmTime(unit);
201:
202: /*
203: * Initialize miscellaneous peer variables
204: */
205: memcpy((char *)&pp->refid, REFID, 4);
206: if (up->shm != 0) {
207: up->shm->precision = PRECISION;
208: peer->precision = up->shm->precision;
209: up->shm->valid=0;
210: up->shm->nsamples=NSAMPLES;
211: pp->clockdesc = DESCRIPTION;
212: return (1);
213: }
214: else {
215: return 0;
216: }
217: }
218:
219:
220: /*
221: * shm_shutdown - shut down the clock
222: */
223: static void
224: shm_shutdown(
225: int unit,
226: struct peer *peer
227: )
228: {
229: struct refclockproc *pp;
230: struct shmunit *up;
231:
232: pp = peer->procptr;
233: up = (struct shmunit *)pp->unitptr;
234:
235: if (NULL == up)
236: return;
237: #ifndef SYS_WINNT
238: /* HMS: shmdt()wants char* or const void * */
239: (void) shmdt ((char *)up->shm);
240: #else
241: UnmapViewOfFile (up->shm);
242: #endif
243: free(up);
244: }
245:
246:
247: /*
248: * shm_timer - called every second
249: */
250: static void
251: shm_timer(int unit, struct peer *peer)
252: {
253: if (OLDWAY)
254: return;
255:
256: shm_peek(unit, peer);
257: }
258:
259:
260: /*
261: * shm_poll - called by the transmit procedure
262: */
263: static void
264: shm_poll(
265: int unit,
266: struct peer *peer
267: )
268: {
269: struct refclockproc *pp;
270: int ok;
271:
272: pp = peer->procptr;
273:
274: if (OLDWAY) {
275: ok = shm_peek(unit, peer);
276: if (!ok) return;
277: }
278:
279: /*
280: * Process median filter samples. If none received, declare a
281: * timeout and keep going.
282: */
283: if (pp->coderecv == pp->codeproc) {
284: refclock_report(peer, CEVNT_TIMEOUT);
285: shm_clockstats(unit, peer);
286: return;
287: }
288: pp->lastref = pp->lastrec;
289: refclock_receive(peer);
290: shm_clockstats(unit, peer);
291: }
292:
293: /*
294: * shm_peek - try to grab a sample
295: */
296: int shm_peek(
297: int unit,
298: struct peer *peer
299: )
300: {
301: struct refclockproc *pp;
302: struct shmunit *up;
303: struct shmTime *shm;
304:
305: /*
306: * This is the main routine. It snatches the time from the shm
307: * board and tacks on a local timestamp.
308: */
309: pp = peer->procptr;
310: up = (struct shmunit*)pp->unitptr;
311: up->ticks++;
312: if (up->shm == 0) {
313: /* try to map again - this may succeed if meanwhile some-
314: body has ipcrm'ed the old (unaccessible) shared mem segment */
315: up->shm = getShmTime(unit);
316: }
317: shm = up->shm;
318: if (shm == 0) {
319: refclock_report(peer, CEVNT_FAULT);
320: return(0);
321: }
322: if (shm->valid) {
323: struct timeval tvr;
324: struct timeval tvt;
325: struct tm *t;
326: int ok=1;
327: tvr.tv_sec = 0;
328: tvr.tv_usec = 0;
329: tvt.tv_sec = 0;
330: tvt.tv_usec = 0;
331: switch (shm->mode) {
332: case 0: {
333: tvr.tv_sec=shm->receiveTimeStampSec;
334: tvr.tv_usec=shm->receiveTimeStampUSec;
335: tvt.tv_sec=shm->clockTimeStampSec;
336: tvt.tv_usec=shm->clockTimeStampUSec;
337: }
338: break;
339: case 1: {
340: int cnt=shm->count;
341: tvr.tv_sec=shm->receiveTimeStampSec;
342: tvr.tv_usec=shm->receiveTimeStampUSec;
343: tvt.tv_sec=shm->clockTimeStampSec;
344: tvt.tv_usec=shm->clockTimeStampUSec;
345: ok=(cnt==shm->count);
346: }
347: break;
348: default:
349: msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",shm->mode);
350: }
351: shm->valid=0;
352: if (ok) {
353: time_t help; /* XXX NetBSD has incompatible tv_sec */
354:
355: TVTOTS(&tvr,&pp->lastrec);
356: pp->lastrec.l_ui += JAN_1970;
357: /* pp->lasttime = current_time; */
358: pp->polls++;
359: help = tvt.tv_sec;
360: t = gmtime (&help);
361: pp->day=t->tm_yday+1;
362: pp->hour=t->tm_hour;
363: pp->minute=t->tm_min;
364: pp->second=t->tm_sec;
365: pp->nsec=tvt.tv_usec * 1000;
366: peer->precision=shm->precision;
367: pp->leap=shm->leap;
368: }
369: else {
370: refclock_report(peer, CEVNT_FAULT);
371: msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
372: up->clash++;
373: return(0);
374: }
375: }
376: else {
377: refclock_report(peer, CEVNT_TIMEOUT);
378: up->notready++;
379: return(0);
380: }
381: if (!refclock_process(pp)) {
382: refclock_report(peer, CEVNT_BADTIME);
383: up->bad++;
384: return(0);
385: }
386: up->good++;
387: return(1);
388: }
389:
390: /*
391: * shm_clockstats - dump and reset counters
392: */
393: void shm_clockstats(
394: int unit,
395: struct peer *peer
396: )
397: {
398: struct refclockproc *pp;
399: struct shmunit *up;
400: char logbuf[256];
401:
402: pp = peer->procptr;
403: up = (struct shmunit*)pp->unitptr;
404:
405: if (!(pp->sloppyclockflag & CLK_FLAG4)) return;
406:
407: snprintf(logbuf, sizeof(logbuf), "%3d %3d %3d %3d %3d",
408: up->ticks, up->good, up->notready, up->bad, up->clash);
409: record_clock_stats(&peer->srcadr, logbuf);
410:
411: up->ticks = up->good = up->notready =up->bad = up->clash = 0;
412:
413: }
414:
415: #else
416: int refclock_shm_bs;
417: #endif /* REFCLOCK */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>