Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / ntpd / refclock_shm.c
blob50063d638f2601a47b3771ca423702a7a157d618
1 /* $NetBSD: refclock_shm.c,v 1.5 2006/06/11 19:34:12 kardel Exp $ */
3 /*
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
9 * PB 18.3.97
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #if defined(REFCLOCK) && defined(CLOCK_SHM)
18 #include "ntpd.h"
19 #undef fileno
20 #include "ntp_io.h"
21 #undef fileno
22 #include "ntp_refclock.h"
23 #undef fileno
24 #include "ntp_unixtime.h"
25 #undef fileno
26 #include "ntp_stdlib.h"
28 #undef fileno
29 #include <ctype.h>
30 #undef fileno
32 #ifndef SYS_WINNT
33 # include <sys/ipc.h>
34 # include <sys/shm.h>
35 # include <assert.h>
36 # include <unistd.h>
37 # include <stdio.h>
38 #endif
41 * This driver supports a reference clock attached thru shared memory
42 */
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 */
54 * Function prototypes
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 *);
61 * Transfer vector
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 */
72 struct shmTime {
73 int mode; /* 0 - if valid set
74 * use values,
75 * clear valid
76 * 1 - if valid set
77 * if count before and after read of values is equal,
78 * use values
79 * clear valid
81 int count;
82 time_t clockTimeStampSec;
83 int clockTimeStampUSec;
84 time_t receiveTimeStampSec;
85 int receiveTimeStampUSec;
86 int leap;
87 int precision;
88 int nsamples;
89 int valid;
90 int dummy[10];
93 struct shmTime *getShmTime(int);
95 struct shmTime *getShmTime (int unit) {
96 #ifndef SYS_WINNT
97 int shmid=0;
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));
104 return 0;
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));
110 return 0;
112 return p;
114 #else
115 char buf[10];
116 LPSECURITY_ATTRIBUTES psec=0;
117 HANDLE shmid=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);
124 return 0;
126 if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
127 msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
128 return 0;
130 sa.nLength=sizeof (SECURITY_ATTRIBUTES);
131 sa.lpSecurityDescriptor=&sd;
132 sa.bInheritHandle=0;
133 psec=&sa;
135 shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
136 0, sizeof (struct shmTime),buf);
137 if (!shmid) { /*error*/
138 char buf[1000];
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);
142 return 0;
144 else {
145 struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
146 FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
147 if (p==0) { /*error*/
148 char buf[1000];
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);
152 return 0;
154 return p;
156 #endif
159 * shm_start - attach to shared memory
161 static int
162 shm_start(
163 int unit,
164 struct peer *peer
167 struct refclockproc *pp;
168 pp = peer->procptr;
169 pp->io.clock_recv = noentry;
170 pp->io.srcclock = (caddr_t)peer;
171 pp->io.datalen = 0;
172 pp->io.fd = -1;
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;
185 return (1);
187 else {
188 return 0;
194 * shm_shutdown - shut down the clock
196 static void
197 shm_shutdown(
198 int unit,
199 struct peer *peer
202 register struct shmTime *up;
203 struct refclockproc *pp;
205 pp = peer->procptr;
206 up = (struct shmTime *)pp->unitptr;
207 #ifndef SYS_WINNT
208 /* HMS: shmdt()wants char* or const void * */
209 (void) shmdt (up);
210 #else
211 UnmapViewOfFile (up);
212 #endif
217 * shm_poll - called by the transmit procedure
219 static void
220 shm_poll(
221 int unit,
222 struct peer *peer
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.
232 pp = peer->procptr;
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
236 segment */
237 pp->unitptr = (caddr_t)getShmTime(unit);
238 up = (struct shmTime*)pp->unitptr;
240 if (up==0) {
241 refclock_report(peer, CEVNT_FAULT);
242 return;
244 if (up->valid) {
245 struct timeval tvr;
246 struct timeval tvt;
247 struct tm *t;
248 int ok=1;
249 tvr.tv_sec = 0;
250 tvr.tv_usec = 0;
251 tvt.tv_sec = 0;
252 tvt.tv_usec = 0;
253 switch (up->mode) {
254 case 0: {
255 tvr.tv_sec=up->receiveTimeStampSec;
256 tvr.tv_usec=up->receiveTimeStampUSec;
257 tvt.tv_sec=up->clockTimeStampSec;
258 tvt.tv_usec=up->clockTimeStampUSec;
260 break;
261 case 1: {
262 int cnt=up->count;
263 tvr.tv_sec=up->receiveTimeStampSec;
264 tvr.tv_usec=up->receiveTimeStampUSec;
265 tvt.tv_sec=up->clockTimeStampSec;
266 tvt.tv_usec=up->clockTimeStampUSec;
267 ok=(cnt==up->count);
269 break;
270 default:
271 msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
273 up->valid=0;
274 if (ok) {
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; */
280 pp->polls++;
281 help = tvt.tv_sec;
282 t = gmtime (&help);
283 pp->day=t->tm_yday+1;
284 pp->hour=t->tm_hour;
285 pp->minute=t->tm_min;
286 pp->second=t->tm_sec;
287 pp->nsec=tvt.tv_usec * 1000;
288 peer->precision=up->precision;
289 pp->leap=up->leap;
291 else {
292 refclock_report(peer, CEVNT_FAULT);
293 msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
294 return;
297 else {
298 refclock_report(peer, CEVNT_TIMEOUT);
300 msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
302 return;
304 if (!refclock_process(pp)) {
305 refclock_report(peer, CEVNT_BADTIME);
306 return;
308 pp->lastref = pp->lastrec;
309 refclock_receive(peer);
312 #else
313 int refclock_shm_bs;
314 #endif /* REFCLOCK */