Logo Search packages:      
Sourcecode: radioclk version File versions  Download package

refclock_shm.c

/*
 * 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 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
      return 0;
}
/*
 * 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
      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;
            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) {
                  TVTOTS(&tvr,&pp->lastrec);
                  pp->lastrec.l_ui += JAN_1970;
                  /* pp->lasttime = current_time; */
                  pp->polls++;
                  t=gmtime (&tvt.tv_sec);
                  pp->day=t->tm_yday+1;
                  pp->hour=t->tm_hour;
                  pp->minute=t->tm_min;
                  pp->second=t->tm_sec;
                  pp->msec=0;
                  pp->usec=tvt.tv_usec;
                  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);
            if (!(pp->sloppyclockflag & CLK_FLAG3))
                  msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
            return;
      }
      if (!refclock_process(pp)) {
            refclock_report(peer, CEVNT_BADTIME);
            return;
      }
      refclock_receive(peer);
}

#else
int refclock_shm_bs;
#endif /* REFCLOCK */

Generated by  Doxygen 1.6.0   Back to index