1 /* $NetBSD: refclock_shm.c,v 1.5 2006/06/11 19:34:12 kardel Exp $ */
4 * refclock_shm - clock driver for utc via shared memory
5 * - under construction -
6 * To add new modes: Extend or union the shmTime-struct. Do not
7 * extend/shrink size, because otherwise existing implementations
8 * will specify wrong size of shared memory-segment
16 #if defined(REFCLOCK) && defined(CLOCK_SHM)
22 #include "ntp_refclock.h"
24 #include "ntp_unixtime.h"
26 #include "ntp_stdlib.h"
41 * This driver supports a reference clock attached thru shared memory
45 * SHM interface definitions
47 #define PRECISION (-1) /* precision assumed (0.5 s) */
48 #define REFID "SHM" /* reference ID */
49 #define DESCRIPTION "SHM/Shared memory interface"
51 #define NSAMPLES 3 /* stages of median filter */
56 static int shm_start (int, struct peer
*);
57 static void shm_shutdown (int, struct peer
*);
58 static void shm_poll (int unit
, struct peer
*);
63 struct refclock refclock_shm
= {
64 shm_start
, /* start up driver */
65 shm_shutdown
, /* shut down driver */
66 shm_poll
, /* transmit poll message */
67 noentry
, /* not used */
68 noentry
, /* initialize driver (not used) */
69 noentry
, /* not used */
70 NOFLAGS
/* not used */
73 int mode
; /* 0 - if valid set
77 * if count before and after read of values is equal,
82 time_t clockTimeStampSec
;
83 int clockTimeStampUSec
;
84 time_t receiveTimeStampSec
;
85 int receiveTimeStampUSec
;
93 struct shmTime
*getShmTime(int);
95 struct shmTime
*getShmTime (int unit
) {
99 assert (unit
<10); /* MAXUNIT is 4, so should never happen */
100 shmid
=shmget (0x4e545030+unit
, sizeof (struct shmTime
),
101 IPC_CREAT
|(unit
<2?0700:0777));
102 if (shmid
==-1) { /*error */
103 msyslog(LOG_ERR
,"SHM shmget (unit %d): %s",unit
,strerror(errno
));
106 else { /* no error */
107 struct shmTime
*p
=(struct shmTime
*)shmat (shmid
, 0, 0);
108 if ((int)(long)p
==-1) { /* error */
109 msyslog(LOG_ERR
,"SHM shmat (unit %d): %s",unit
,strerror(errno
));
116 LPSECURITY_ATTRIBUTES psec
=0;
118 SECURITY_DESCRIPTOR sd
;
119 SECURITY_ATTRIBUTES sa
;
120 sprintf (buf
,"NTP%d",unit
);
121 if (unit
>=2) { /* world access */
122 if (!InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
)) {
123 msyslog(LOG_ERR
,"SHM InitializeSecurityDescriptor (unit %d): %m",unit
);
126 if (!SetSecurityDescriptorDacl(&sd
,1,0,0)) {
127 msyslog(LOG_ERR
,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit
);
130 sa
.nLength
=sizeof (SECURITY_ATTRIBUTES
);
131 sa
.lpSecurityDescriptor
=&sd
;
135 shmid
=CreateFileMapping ((HANDLE
)0xffffffff, psec
, PAGE_READWRITE
,
136 0, sizeof (struct shmTime
),buf
);
137 if (!shmid
) { /*error*/
139 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
,
140 0, GetLastError (), 0, buf
, sizeof (buf
), 0);
141 msyslog(LOG_ERR
,"SHM CreateFileMapping (unit %d): %s",unit
,buf
);
145 struct shmTime
*p
=(struct shmTime
*) MapViewOfFile (shmid
,
146 FILE_MAP_WRITE
, 0, 0, sizeof (struct shmTime
));
147 if (p
==0) { /*error*/
149 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
,
150 0, GetLastError (), 0, buf
, sizeof (buf
), 0);
151 msyslog(LOG_ERR
,"SHM MapViewOfFile (unit %d): %s",unit
,buf
);
159 * shm_start - attach to shared memory
167 struct refclockproc
*pp
;
169 pp
->io
.clock_recv
= noentry
;
170 pp
->io
.srcclock
= (caddr_t
)peer
;
173 pp
->unitptr
= (caddr_t
)getShmTime(unit
);
176 * Initialize miscellaneous peer variables
178 memcpy((char *)&pp
->refid
, REFID
, 4);
179 if (pp
->unitptr
!=0) {
180 ((struct shmTime
*)pp
->unitptr
)->precision
=PRECISION
;
181 peer
->precision
= ((struct shmTime
*)pp
->unitptr
)->precision
;
182 ((struct shmTime
*)pp
->unitptr
)->valid
=0;
183 ((struct shmTime
*)pp
->unitptr
)->nsamples
=NSAMPLES
;
184 pp
->clockdesc
= DESCRIPTION
;
194 * shm_shutdown - shut down the clock
202 register struct shmTime
*up
;
203 struct refclockproc
*pp
;
206 up
= (struct shmTime
*)pp
->unitptr
;
208 /* HMS: shmdt()wants char* or const void * */
211 UnmapViewOfFile (up
);
217 * shm_poll - called by the transmit procedure
225 register struct shmTime
*up
;
226 struct refclockproc
*pp
;
229 * This is the main routine. It snatches the time from the shm
230 * board and tacks on a local timestamp.
233 up
= (struct shmTime
*)pp
->unitptr
;
234 if (up
==0) { /* try to map again - this may succeed if meanwhile some-
235 body has ipcrm'ed the old (unaccessible) shared mem
237 pp
->unitptr
= (caddr_t
)getShmTime(unit
);
238 up
= (struct shmTime
*)pp
->unitptr
;
241 refclock_report(peer
, CEVNT_FAULT
);
255 tvr
.tv_sec
=up
->receiveTimeStampSec
;
256 tvr
.tv_usec
=up
->receiveTimeStampUSec
;
257 tvt
.tv_sec
=up
->clockTimeStampSec
;
258 tvt
.tv_usec
=up
->clockTimeStampUSec
;
263 tvr
.tv_sec
=up
->receiveTimeStampSec
;
264 tvr
.tv_usec
=up
->receiveTimeStampUSec
;
265 tvt
.tv_sec
=up
->clockTimeStampSec
;
266 tvt
.tv_usec
=up
->clockTimeStampUSec
;
271 msyslog (LOG_ERR
, "SHM: bad mode found in shared memory: %d",up
->mode
);
275 time_t help
; /* XXX NetBSD has incompatible tv_sec */
277 TVTOTS(&tvr
,&pp
->lastrec
);
278 pp
->lastrec
.l_ui
+= JAN_1970
;
279 /* pp->lasttime = current_time; */
283 pp
->day
=t
->tm_yday
+1;
285 pp
->minute
=t
->tm_min
;
286 pp
->second
=t
->tm_sec
;
287 pp
->nsec
=tvt
.tv_usec
* 1000;
288 peer
->precision
=up
->precision
;
292 refclock_report(peer
, CEVNT_FAULT
);
293 msyslog (LOG_NOTICE
, "SHM: access clash in shared memory");
298 refclock_report(peer
, CEVNT_TIMEOUT
);
300 msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
304 if (!refclock_process(pp
)) {
305 refclock_report(peer
, CEVNT_BADTIME
);
308 pp
->lastref
= pp
->lastrec
;
309 refclock_receive(peer
);
314 #endif /* REFCLOCK */