PageRenderTime 42ms CodeModel.GetById 14ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/ntpd/refclock_shm.c

https://bitbucket.org/freebsd/freebsd-head/
C | 312 lines | 240 code | 22 blank | 50 comment | 20 complexity | 5b9c01d3f4f2d9316ad5df2c6a866218 MD5 | raw file
  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/*
 43 * SHM interface definitions
 44 */
 45#define PRECISION       (-1)    /* precision assumed (0.5 s) */
 46#define REFID           "SHM"   /* reference ID */
 47#define DESCRIPTION     "SHM/Shared memory interface"
 48
 49#define NSAMPLES        3       /* stages of median filter */
 50
 51/*
 52 * Function prototypes
 53 */
 54static  int     shm_start       (int, struct peer *);
 55static  void    shm_shutdown    (int, struct peer *);
 56static  void    shm_poll        (int unit, struct peer *);
 57
 58/*
 59 * Transfer vector
 60 */
 61struct  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 */
 69};
 70struct shmTime {
 71	int    mode; /* 0 - if valid set
 72		      *       use values, 
 73		      *       clear valid
 74		      * 1 - if valid set 
 75		      *       if count before and after read of values is equal,
 76		      *         use values 
 77		      *       clear valid
 78		      */
 79	int    count;
 80	time_t clockTimeStampSec;
 81	int    clockTimeStampUSec;
 82	time_t receiveTimeStampSec;
 83	int    receiveTimeStampUSec;
 84	int    leap;
 85	int    precision;
 86	int    nsamples;
 87	int    valid;
 88	int    dummy[10]; 
 89};
 90
 91struct shmTime *getShmTime(int);
 92
 93struct shmTime *getShmTime (int unit) {
 94#ifndef SYS_WINNT
 95	int shmid=0;
 96
 97	assert (unit<10); /* MAXUNIT is 4, so should never happen */
 98	shmid=shmget (0x4e545030+unit, sizeof (struct shmTime), 
 99		      IPC_CREAT|(unit<2?0700:0777));
100	if (shmid==-1) { /*error */
101		msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
102		return 0;
103	}
104	else { /* no error  */
105		struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
106		if ((int)(long)p==-1) { /* error */
107			msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
108			return 0;
109		}
110		return p;
111	}
112#else
113	char buf[10];
114	LPSECURITY_ATTRIBUTES psec=0;
115	HANDLE shmid=0;
116	SECURITY_DESCRIPTOR sd;
117	SECURITY_ATTRIBUTES sa;
118	sprintf (buf,"NTP%d",unit);
119	if (unit>=2) { /* world access */
120		if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
121			msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
122			return 0;
123		}
124		if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
125			msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
126			return 0;
127		}
128		sa.nLength=sizeof (SECURITY_ATTRIBUTES);
129		sa.lpSecurityDescriptor=&sd;
130		sa.bInheritHandle=0;
131		psec=&sa;
132	}
133	shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
134				 0, sizeof (struct shmTime),buf);
135	if (!shmid) { /*error*/
136		char buf[1000];
137		FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
138			       0, GetLastError (), 0, buf, sizeof (buf), 0);
139		msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
140		return 0;
141	}
142	else {
143		struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid, 
144								    FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
145		if (p==0) { /*error*/
146			char buf[1000];
147			FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
148				       0, GetLastError (), 0, buf, sizeof (buf), 0);
149			msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
150			return 0;
151		}
152		return p;
153	}
154#endif
155}
156/*
157 * shm_start - attach to shared memory
158 */
159static int
160shm_start(
161	int unit,
162	struct peer *peer
163	)
164{
165	struct refclockproc *pp;
166	pp = peer->procptr;
167	pp->io.clock_recv = noentry;
168	pp->io.srcclock = (caddr_t)peer;
169	pp->io.datalen = 0;
170	pp->io.fd = -1;
171	pp->unitptr = (caddr_t)getShmTime(unit);
172
173	/*
174	 * Initialize miscellaneous peer variables
175	 */
176	memcpy((char *)&pp->refid, REFID, 4);
177	if (pp->unitptr!=0) {
178		((struct shmTime*)pp->unitptr)->precision=PRECISION;
179		peer->precision = ((struct shmTime*)pp->unitptr)->precision;
180		((struct shmTime*)pp->unitptr)->valid=0;
181		((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
182		pp->clockdesc = DESCRIPTION;
183		return (1);
184	}
185	else {
186		return 0;
187	}
188}
189
190
191/*
192 * shm_shutdown - shut down the clock
193 */
194static void
195shm_shutdown(
196	int unit,
197	struct peer *peer
198	)
199{
200	register struct shmTime *up;
201	struct refclockproc *pp;
202
203	pp = peer->procptr;
204	up = (struct shmTime *)pp->unitptr;
205#ifndef SYS_WINNT
206	/* HMS: shmdt()wants char* or const void * */
207	(void) shmdt (up);
208#else
209	UnmapViewOfFile (up);
210#endif
211}
212
213
214/*
215 * shm_poll - called by the transmit procedure
216 */
217static void
218shm_poll(
219	int unit,
220	struct peer *peer
221	)
222{
223	register struct shmTime *up;
224	struct refclockproc *pp;
225
226	/*
227	 * This is the main routine. It snatches the time from the shm
228	 * board and tacks on a local timestamp.
229	 */
230	pp = peer->procptr;
231	up = (struct shmTime*)pp->unitptr;
232	if (up==0) { /* try to map again - this may succeed if meanwhile some-
233			body has ipcrm'ed the old (unaccessible) shared mem
234			segment  */
235		pp->unitptr = (caddr_t)getShmTime(unit);
236		up = (struct shmTime*)pp->unitptr;
237	}
238	if (up==0) {
239		refclock_report(peer, CEVNT_FAULT);
240		return;
241	}
242	if (up->valid) {
243		struct timeval tvr;
244		struct timeval tvt;
245		struct tm *t;
246		int ok=1;
247		tvr.tv_sec = 0;
248		tvr.tv_usec = 0;
249		tvt.tv_sec = 0;
250		tvt.tv_usec = 0;
251		switch (up->mode) {
252		    case 0: {
253			    tvr.tv_sec=up->receiveTimeStampSec;
254			    tvr.tv_usec=up->receiveTimeStampUSec;
255			    tvt.tv_sec=up->clockTimeStampSec;
256			    tvt.tv_usec=up->clockTimeStampUSec;
257		    }
258		    break;
259		    case 1: {
260			    int cnt=up->count;
261			    tvr.tv_sec=up->receiveTimeStampSec;
262			    tvr.tv_usec=up->receiveTimeStampUSec;
263			    tvt.tv_sec=up->clockTimeStampSec;
264			    tvt.tv_usec=up->clockTimeStampUSec;
265			    ok=(cnt==up->count);
266		    }
267		    break;
268		    default:
269			msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
270		}
271		up->valid=0;
272		if (ok) {
273			time_t help;	/* XXX NetBSD has incompatible tv_sec */
274
275			TVTOTS(&tvr,&pp->lastrec);
276			pp->lastrec.l_ui += JAN_1970;
277			/* pp->lasttime = current_time; */
278			pp->polls++;
279			help = tvt.tv_sec;
280			t = gmtime (&help);
281			pp->day=t->tm_yday+1;
282			pp->hour=t->tm_hour;
283			pp->minute=t->tm_min;
284			pp->second=t->tm_sec;
285			pp->nsec=tvt.tv_usec * 1000;
286			peer->precision=up->precision;
287			pp->leap=up->leap;
288		} 
289		else {
290			refclock_report(peer, CEVNT_FAULT);
291			msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
292			return;
293		}
294	}
295	else {
296		refclock_report(peer, CEVNT_TIMEOUT);
297		/*
298		msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
299		*/
300		return;
301	}
302	if (!refclock_process(pp)) {
303		refclock_report(peer, CEVNT_BADTIME);
304		return;
305	}
306	pp->lastref = pp->lastrec;
307	refclock_receive(peer);
308}
309
310#else
311int refclock_shm_bs;
312#endif /* REFCLOCK */