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
14 #if defined(REFCLOCK) && defined(CLOCK_SHM)
20 #include "ntp_refclock.h"
22 #include "ntp_unixtime.h"
24 #include "ntp_stdlib.h"
39 * This driver supports a reference clock attached thru shared memory
43 * SHM interface definitions
45 #define PRECISION (-1) /* precision assumed (0.5 s) */
46 #define REFID "SHM" /* reference ID */
47 #define DESCRIPTION "SHM/Shared memory interface"
49 #define NSAMPLES 3 /* stages of median filter */
54 static int shm_start (int, struct peer *);
55 static void shm_shutdown (int, struct peer *);
56 static void shm_poll (int unit, struct peer *);
61 struct refclock refclock_shm = {
62 shm_start, /* start up driver */
63 shm_shutdown, /* shut down driver */
64 shm_poll, /* transmit poll message */
65 noentry, /* not used */
66 noentry, /* initialize driver (not used) */
67 noentry, /* not used */
68 NOFLAGS /* not used */
71 int mode; /* 0 - if valid set
75 * if count before and after read of values is equal,
80 time_t clockTimeStampSec;
81 int clockTimeStampUSec;
82 time_t receiveTimeStampSec;
83 int receiveTimeStampUSec;
90 struct shmTime *getShmTime (int unit) {
94 assert (unit<10); /* MAXUNIT is 4, so should never happen */
95 shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
96 IPC_CREAT|(unit<2?0700:0777));
97 if (shmid==-1) { /*error */
98 msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
101 else { /* no error */
102 struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
103 if ((int)(long)p==-1) { /* error */
104 msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
111 LPSECURITY_ATTRIBUTES psec=0;
113 SECURITY_DESCRIPTOR sd;
114 SECURITY_ATTRIBUTES sa;
115 sprintf (buf,"NTP%d",unit);
116 if (unit>=2) { /* world access */
117 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
118 msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
121 if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
122 msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
125 sa.nLength=sizeof (SECURITY_ATTRIBUTES);
126 sa.lpSecurityDescriptor=&sd;
130 shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
131 0, sizeof (struct shmTime),buf);
132 if (!shmid) { /*error*/
134 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
135 0, GetLastError (), 0, buf, sizeof (buf), 0);
136 msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
140 struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
141 FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
142 if (p==0) { /*error*/
144 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
145 0, GetLastError (), 0, buf, sizeof (buf), 0);
146 msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
155 * shm_start - attach to shared memory
163 struct refclockproc *pp;
165 pp->io.clock_recv = noentry;
166 pp->io.srcclock = (caddr_t)peer;
169 pp->unitptr = (caddr_t)getShmTime(unit);
172 * Initialize miscellaneous peer variables
174 memcpy((char *)&pp->refid, REFID, 4);
175 if (pp->unitptr!=0) {
176 ((struct shmTime*)pp->unitptr)->precision=PRECISION;
177 peer->precision = ((struct shmTime*)pp->unitptr)->precision;
178 ((struct shmTime*)pp->unitptr)->valid=0;
179 ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
180 pp->clockdesc = DESCRIPTION;
190 * shm_shutdown - shut down the clock
198 register struct shmTime *up;
199 struct refclockproc *pp;
202 up = (struct shmTime *)pp->unitptr;
206 UnmapViewOfFile (up);
212 * shm_poll - called by the transmit procedure
220 register struct shmTime *up;
221 struct refclockproc *pp;
224 * This is the main routine. It snatches the time from the shm
225 * board and tacks on a local timestamp.
228 up = (struct shmTime*)pp->unitptr;
229 if (up==0) { /* try to map again - this may succeed if meanwhile some-
230 body has ipcrm'ed the old (unaccessible) shared mem
232 pp->unitptr = (caddr_t)getShmTime(unit);
233 up = (struct shmTime*)pp->unitptr;
236 refclock_report(peer, CEVNT_FAULT);
246 tvr.tv_sec=up->receiveTimeStampSec;
247 tvr.tv_usec=up->receiveTimeStampUSec;
248 tvt.tv_sec=up->clockTimeStampSec;
249 tvt.tv_usec=up->clockTimeStampUSec;
254 tvr.tv_sec=up->receiveTimeStampSec;
255 tvr.tv_usec=up->receiveTimeStampUSec;
256 tvt.tv_sec=up->clockTimeStampSec;
257 tvt.tv_usec=up->clockTimeStampUSec;
262 msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
266 TVTOTS(&tvr,&pp->lastrec);
267 pp->lastrec.l_ui += JAN_1970;
268 /* pp->lasttime = current_time; */
270 t=gmtime (&tvt.tv_sec);
271 pp->day=t->tm_yday+1;
273 pp->minute=t->tm_min;
274 pp->second=t->tm_sec;
276 pp->usec=tvt.tv_usec;
277 peer->precision=up->precision;
281 refclock_report(peer, CEVNT_FAULT);
282 msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
287 refclock_report(peer, CEVNT_TIMEOUT);
288 msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
291 if (!refclock_process(pp)) {
292 refclock_report(peer, CEVNT_BADTIME);
295 refclock_receive(peer);
300 #endif /* REFCLOCK */