/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
- /*
- * refclock_shm - clock driver for utc via shared memory
- * - under construction -
- * To add new modes: Extend or union the shmTime-struct. Do not
- * extend/shrink size, because otherwise existing implementations
- * will specify wrong size of shared memory-segment
- * PB 18.3.97
- */
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #if defined(REFCLOCK) && defined(CLOCK_SHM)
- #include "ntpd.h"
- #undef fileno
- #include "ntp_io.h"
- #undef fileno
- #include "ntp_refclock.h"
- #undef fileno
- #include "ntp_unixtime.h"
- #undef fileno
- #include "ntp_stdlib.h"
- #undef fileno
- #include <ctype.h>
- #undef fileno
- #ifndef SYS_WINNT
- # include <sys/ipc.h>
- # include <sys/shm.h>
- # include <assert.h>
- # include <unistd.h>
- # include <stdio.h>
- #endif
- /*
- * This driver supports a reference clock attached thru shared memory
- */
- /*
- * SHM interface definitions
- */
- #define PRECISION (-1) /* precision assumed (0.5 s) */
- #define REFID "SHM" /* reference ID */
- #define DESCRIPTION "SHM/Shared memory interface"
- #define NSAMPLES 3 /* stages of median filter */
- /*
- * Function prototypes
- */
- static int shm_start (int, struct peer *);
- static void shm_shutdown (int, struct peer *);
- static void shm_poll (int unit, struct peer *);
- /*
- * Transfer vector
- */
- struct refclock refclock_shm = {
- shm_start, /* start up driver */
- shm_shutdown, /* shut down driver */
- shm_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
- };
- struct shmTime {
- int mode; /* 0 - if valid set
- * use values,
- * clear valid
- * 1 - if valid set
- * if count before and after read of values is equal,
- * use values
- * clear valid
- */
- int count;
- time_t clockTimeStampSec;
- int clockTimeStampUSec;
- time_t receiveTimeStampSec;
- int receiveTimeStampUSec;
- int leap;
- int precision;
- int nsamples;
- int valid;
- int dummy[10];
- };
- struct shmTime *getShmTime(int);
- struct shmTime *getShmTime (int unit) {
- #ifndef SYS_WINNT
- int shmid=0;
- assert (unit<10); /* MAXUNIT is 4, so should never happen */
- shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
- IPC_CREAT|(unit<2?0700:0777));
- if (shmid==-1) { /*error */
- msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
- return 0;
- }
- else { /* no error */
- struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
- if ((int)(long)p==-1) { /* error */
- msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
- return 0;
- }
- return p;
- }
- #else
- char buf[10];
- LPSECURITY_ATTRIBUTES psec=0;
- HANDLE shmid=0;
- SECURITY_DESCRIPTOR sd;
- SECURITY_ATTRIBUTES sa;
- sprintf (buf,"NTP%d",unit);
- if (unit>=2) { /* world access */
- if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
- msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
- return 0;
- }
- if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
- msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
- return 0;
- }
- sa.nLength=sizeof (SECURITY_ATTRIBUTES);
- sa.lpSecurityDescriptor=&sd;
- sa.bInheritHandle=0;
- psec=&sa;
- }
- shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
- 0, sizeof (struct shmTime),buf);
- if (!shmid) { /*error*/
- char buf[1000];
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
- 0, GetLastError (), 0, buf, sizeof (buf), 0);
- msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
- return 0;
- }
- else {
- struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
- FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
- if (p==0) { /*error*/
- char buf[1000];
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
- 0, GetLastError (), 0, buf, sizeof (buf), 0);
- msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
- return 0;
- }
- return p;
- }
- #endif
- }
- /*
- * shm_start - attach to shared memory
- */
- static int
- shm_start(
- int unit,
- struct peer *peer
- )
- {
- struct refclockproc *pp;
- pp = peer->procptr;
- pp->io.clock_recv = noentry;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = -1;
- pp->unitptr = (caddr_t)getShmTime(unit);
- /*
- * Initialize miscellaneous peer variables
- */
- memcpy((char *)&pp->refid, REFID, 4);
- if (pp->unitptr!=0) {
- ((struct shmTime*)pp->unitptr)->precision=PRECISION;
- peer->precision = ((struct shmTime*)pp->unitptr)->precision;
- ((struct shmTime*)pp->unitptr)->valid=0;
- ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
- pp->clockdesc = DESCRIPTION;
- return (1);
- }
- else {
- return 0;
- }
- }
- /*
- * shm_shutdown - shut down the clock
- */
- static void
- shm_shutdown(
- int unit,
- struct peer *peer
- )
- {
- register struct shmTime *up;
- struct refclockproc *pp;
- pp = peer->procptr;
- up = (struct shmTime *)pp->unitptr;
- #ifndef SYS_WINNT
- /* HMS: shmdt()wants char* or const void * */
- (void) shmdt (up);
- #else
- UnmapViewOfFile (up);
- #endif
- }
- /*
- * shm_poll - called by the transmit procedure
- */
- static void
- shm_poll(
- int unit,
- struct peer *peer
- )
- {
- register struct shmTime *up;
- struct refclockproc *pp;
- /*
- * This is the main routine. It snatches the time from the shm
- * board and tacks on a local timestamp.
- */
- pp = peer->procptr;
- up = (struct shmTime*)pp->unitptr;
- if (up==0) { /* try to map again - this may succeed if meanwhile some-
- body has ipcrm'ed the old (unaccessible) shared mem
- segment */
- pp->unitptr = (caddr_t)getShmTime(unit);
- up = (struct shmTime*)pp->unitptr;
- }
- if (up==0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- if (up->valid) {
- struct timeval tvr;
- struct timeval tvt;
- struct tm *t;
- int ok=1;
- tvr.tv_sec = 0;
- tvr.tv_usec = 0;
- tvt.tv_sec = 0;
- tvt.tv_usec = 0;
- switch (up->mode) {
- case 0: {
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
- }
- break;
- case 1: {
- int cnt=up->count;
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
- ok=(cnt==up->count);
- }
- break;
- default:
- msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
- }
- up->valid=0;
- if (ok) {
- time_t help; /* XXX NetBSD has incompatible tv_sec */
- TVTOTS(&tvr,&pp->lastrec);
- pp->lastrec.l_ui += JAN_1970;
- /* pp->lasttime = current_time; */
- pp->polls++;
- help = tvt.tv_sec;
- t = gmtime (&help);
- pp->day=t->tm_yday+1;
- pp->hour=t->tm_hour;
- pp->minute=t->tm_min;
- pp->second=t->tm_sec;
- pp->nsec=tvt.tv_usec * 1000;
- peer->precision=up->precision;
- pp->leap=up->leap;
- }
- else {
- refclock_report(peer, CEVNT_FAULT);
- msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
- return;
- }
- }
- else {
- refclock_report(peer, CEVNT_TIMEOUT);
- /*
- msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
- */
- return;
- }
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- }
- #else
- int refclock_shm_bs;
- #endif /* REFCLOCK */