source: trunk/third/xntp/xntpd/refclock_shm.c @ 10832

Revision 10832, 9.1 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
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
15#if defined(REFCLOCK) && defined(SHM_CLOCK)
16
17#undef fileno   
18#include <ctype.h>
19#undef fileno   
20#include <sys/time.h>
21#undef fileno   
22
23#include "ntpd.h"
24#undef fileno   
25#include "ntp_io.h"
26#undef fileno   
27#include "ntp_refclock.h"
28#undef fileno   
29#include "ntp_unixtime.h"
30#undef fileno   
31#include "ntp_stdlib.h"
32
33#ifndef SYS_WINNT
34  #include <sys/types.h>
35  #include <sys/ipc.h>
36  #include <sys/shm.h>
37  #include <assert.h>
38  #include <time.h>
39  #include <unistd.h>
40  #include <stdlib.h>
41  #include <stdio.h>
42#endif
43
44/*
45 * This driver supports a reference clock attached thru shared memory
46 */
47
48/*
49 * SHM interface definitions
50 */
51#define PRECISION       (-1)    /* precision assumed (0.5 s) */
52#define REFID           "SHM"   /* reference ID */
53#define DESCRIPTION     "SHM/Shared memory interface"
54
55#define NSAMPLES        3       /* stages of median filter */
56
57/*
58 * Imported from ntp_timer module
59 */
60extern u_long current_time;     /* current time (s) */
61
62/*
63 * Imported from ntpd module
64 */
65extern int debug;               /* global debug flag */
66
67/*
68 * Function prototypes
69 */
70static  int     shm_start       P((int, struct peer *));
71static  void    shm_shutdown    P((int, struct peer *));
72static  void    shm_poll        P((int unit, struct peer *));
73
74/*
75 * Transfer vector
76 */
77struct  refclock refclock_shm = {
78        shm_start,              /* start up driver */
79        shm_shutdown,           /* shut down driver */
80        shm_poll,               /* transmit poll message */
81        noentry,                /* not used */
82        noentry,                /* initialize driver (not used) */
83        noentry,                /* not used */
84        NOFLAGS                 /* not used */
85};
86struct shmTime {
87  int    mode; /* 0 - if valid set
88                *       use values,
89                *       clear valid
90                * 1 - if valid set
91                *       if count before and after read of values is equal,
92                *         use values
93                *       clear valid
94                */
95  int    count;
96  time_t clockTimeStampSec;
97  int    clockTimeStampUSec;
98  time_t receiveTimeStampSec;
99  int    receiveTimeStampUSec;
100  int    leap;
101  int    precision;
102  int    nsamples;
103  int    valid;
104  int    dummy[10];
105};
106struct shmTime *getShmTime (int unit) {
107  #ifndef SYS_WINNT
108    extern char *sys_errlist[ ];
109    extern int sys_nerr;
110    extern int errno;
111    int shmid=0;
112
113    assert (unit<10); // MAXUNIT is 4, so should never happen
114    shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
115                 IPC_CREAT|(unit<2?0700:0777));
116    if (shmid==-1) { //error
117      char buf[20];
118      char *pe=buf;
119      if (errno<sys_nerr)
120        pe=sys_errlist[errno];
121      else {
122        sprintf (buf,"errno=%d",errno);
123      }
124      msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,pe);
125      return 0;
126    }
127    else { // no error
128      struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
129      if ((int)(long)p==-1) { //error
130        char buf[20];
131        char *pe=buf;
132        if (errno<sys_nerr)
133          pe=sys_errlist[errno];
134        else {
135          sprintf (buf,"errno=%d",errno);
136        }
137        msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,pe);
138        return 0;
139      }
140      return p;
141    }
142  #else
143    char buf[10];
144    LPSECURITY_ATTRIBUTES psec=0;
145    HANDLE shmid=0;
146    SECURITY_DESCRIPTOR sd;
147    SECURITY_ATTRIBUTES sa;
148    sprintf (buf,"NTP%d",unit);
149    if (unit>=2) { // world access
150      if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
151        msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
152        return 0;
153      }
154      if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
155        msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
156        return 0;
157      }
158      sa.nLength=sizeof (SECURITY_ATTRIBUTES);
159      sa.lpSecurityDescriptor=&sd;
160      sa.bInheritHandle=0;
161      psec=&sa;
162    }
163    shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
164                                    0, sizeof (struct shmTime),buf);
165    if (!shmid) { //error
166      char buf[1000];
167      FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
168                     0, GetLastError (), 0, buf, sizeof (buf), 0);
169      msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
170      return 0;
171    }
172    else {
173      struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
174                          FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
175      if (p==0) { //error
176        char buf[1000];
177        FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
178                       0, GetLastError (), 0, buf, sizeof (buf), 0);
179        msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
180        return 0;
181      }
182      return p;
183    }
184  #endif
185  return 0;
186}
187/*
188 * shm_start - attach to shared memory
189 */
190static int
191shm_start(unit, peer)
192        int unit;
193        struct peer *peer;
194{
195        struct refclockproc *pp;
196        pp = peer->procptr;
197        pp->io.clock_recv = noentry;
198        pp->io.srcclock = (caddr_t)peer;
199        pp->io.datalen = 0;
200        pp->io.fd = -1;
201        pp->unitptr = (caddr_t)getShmTime(unit);
202
203        /*
204         * Initialize miscellaneous peer variables
205         */
206        memcpy((char *)&pp->refid, REFID, 4);
207        if (pp->unitptr!=0) {
208          ((struct shmTime*)pp->unitptr)->precision=PRECISION;
209          peer->precision = ((struct shmTime*)pp->unitptr)->precision;
210          ((struct shmTime*)pp->unitptr)->valid=0;
211          ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
212          pp->clockdesc = DESCRIPTION;
213          return (1);
214       }
215       else {
216         return 0;
217       }
218}
219
220
221/*
222 * shm_shutdown - shut down the clock
223 */
224static void
225shm_shutdown(unit, peer)
226        int unit;
227        struct peer *peer;
228{
229        register struct shmTime *up;
230        struct refclockproc *pp;
231
232        pp = peer->procptr;
233        up = (struct shmTime *)pp->unitptr;
234#ifndef SYS_WINNT
235        shmdt (up);
236#else
237        UnmapViewOfFile (up);
238#endif
239}
240
241
242/*
243 * shm_poll - called by the transmit procedure
244 */
245static void
246shm_poll(unit, peer)
247        int unit;
248        struct peer *peer;
249{
250        register struct shmTime *up;
251        struct refclockproc *pp;
252
253        /*
254         * This is the main routine. It snatches the time from the shm
255         * board and tacks on a local timestamp.
256         */
257        pp = peer->procptr;
258        up = (struct shmTime*)pp->unitptr;
259        if (up==0) { /* try to map again - this may succeed if meanwhile some-
260                        body has ipcrm'ed the old (unaccessible) shared mem
261                        segment  */
262          pp->unitptr = (caddr_t)getShmTime(unit);
263          up = (struct shmTime*)pp->unitptr;
264        }
265        if (up==0) {
266          refclock_report(peer, CEVNT_FAULT);
267          return;
268        }
269        if (up->valid) {
270          struct timeval tvr;
271          struct timeval tvt;
272          struct tm *t;
273          int ok=1;
274          switch (up->mode) {
275            case 0: {
276              tvr.tv_sec=up->receiveTimeStampSec-172800;
277              tvr.tv_usec=up->receiveTimeStampUSec;
278              tvt.tv_sec=up->clockTimeStampSec;
279              tvt.tv_usec=up->clockTimeStampUSec;
280            }
281            break;
282            case 1: {
283              int cnt=up->count;
284              tvr.tv_sec=up->receiveTimeStampSec-172800;
285              tvr.tv_usec=up->receiveTimeStampUSec;
286              tvt.tv_sec=up->clockTimeStampSec;
287              tvt.tv_usec=up->clockTimeStampUSec;
288              ok=(cnt==up->count);
289            }
290            break;
291            default:
292              msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
293          }
294/*msyslog(LOG_NOTICE,"poll2a tvr.s %d tvr.u %d tvt.s %d tvt.u %d",tvr.tv_sec,tvr.tv_usec,tvt.tv_sec,tvt.tv_usec);*/
295          up->valid=0;
296          if (ok) {
297            TVTOTS(&tvr,&pp->lastrec);
298            pp->lasttime = current_time;
299            pp->polls++;
300            t=gmtime (&tvt.tv_sec);
301            pp->day=t->tm_yday;//+2;
302            pp->hour=t->tm_hour;
303            pp->minute=t->tm_min;
304            pp->second=t->tm_sec;
305            pp->usec=tvt.tv_usec;
306            peer->precision=up->precision;
307            pp->leap=up->leap;
308          }
309          else {
310            refclock_report(peer, CEVNT_FAULT);
311            msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
312            return;
313          }
314        }
315        else {
316          refclock_report(peer, CEVNT_TIMEOUT);
317          msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
318          return;
319        }
320        if (!refclock_process(pp, up->nsamples, up->nsamples)) {
321          refclock_report(peer, CEVNT_BADTIME);
322          return;
323        }
324        refclock_receive(peer, &pp->offset, 0, pp->dispersion,
325            &pp->lastrec, &pp->lastrec, pp->leap);
326}
327
328#else /* not (REFCLOCK && SHM_CLOCK) */
329int refclock_shm_bs;
330#endif /* not (REFCLOCK && SHM_CLOCK) */
331
Note: See TracBrowser for help on using the repository browser.