Annotation of embedaddon/ntp/ntpd/refclock_shm.c, revision 1.1.1.1

1.1       misho       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: /* Temp hack to simplify testing of the old mode. */
                     43: #define OLDWAY 0
                     44: 
                     45: /*
                     46:  * SHM interface definitions
                     47:  */
                     48: #define PRECISION       (-1)    /* precision assumed (0.5 s) */
                     49: #define REFID           "SHM"   /* reference ID */
                     50: #define DESCRIPTION     "SHM/Shared memory interface"
                     51: 
                     52: #define NSAMPLES        3       /* stages of median filter */
                     53: 
                     54: /*
                     55:  * Function prototypes
                     56:  */
                     57: static  int     shm_start       (int unit, struct peer *peer);
                     58: static  void    shm_shutdown    (int unit, struct peer *peer);
                     59: static  void    shm_poll        (int unit, struct peer *peer);
                     60: static  void    shm_timer       (int unit, struct peer *peer);
                     61:        int     shm_peek        (int unit, struct peer *peer);
                     62:        void    shm_clockstats  (int unit, struct peer *peer);
                     63: 
                     64: /*
                     65:  * Transfer vector
                     66:  */
                     67: struct  refclock refclock_shm = {
                     68:        shm_start,              /* start up driver */
                     69:        shm_shutdown,           /* shut down driver */
                     70:        shm_poll,               /* transmit poll message */
                     71:        noentry,                /* not used: control */
                     72:        noentry,                /* not used: init */
                     73:        noentry,                /* not used: buginfo */
                     74:        shm_timer,              /* once per second */
                     75: };
                     76: 
                     77: struct shmTime {
                     78:        int    mode; /* 0 - if valid set
                     79:                      *       use values, 
                     80:                      *       clear valid
                     81:                      * 1 - if valid set 
                     82:                      *       if count before and after read of values is equal,
                     83:                      *         use values 
                     84:                      *       clear valid
                     85:                      */
                     86:        int    count;
                     87:        time_t clockTimeStampSec;
                     88:        int    clockTimeStampUSec;
                     89:        time_t receiveTimeStampSec;
                     90:        int    receiveTimeStampUSec;
                     91:        int    leap;
                     92:        int    precision;
                     93:        int    nsamples;
                     94:        int    valid;
                     95:        int    dummy[10]; 
                     96: };
                     97: 
                     98: struct shmunit {
                     99:        struct shmTime *shm;    /* pointer to shared memory segment */
                    100: 
                    101:        /* debugging/monitoring counters - reset when printed */
                    102:        int ticks;              /* number of attempts to read data*/
                    103:        int good;               /* number of valid samples */
                    104:        int notready;           /* number of peeks without data ready */
                    105:        int bad;                /* number of invalid samples */
                    106:        int clash;              /* number of access clashes while reading */
                    107: };
                    108: 
                    109: 
                    110: struct shmTime *getShmTime(int);
                    111: 
                    112: struct shmTime *getShmTime (int unit) {
                    113: #ifndef SYS_WINNT
                    114:        int shmid=0;
                    115: 
                    116:        /* 0x4e545030 is NTP0.
                    117:         * Big units will give non-ascii but that's OK
                    118:         * as long as everybody does it the same way. 
                    119:         */
                    120:        shmid=shmget (0x4e545030+unit, sizeof (struct shmTime), 
                    121:                      IPC_CREAT|(unit<2?0600:0666));
                    122:        if (shmid==-1) { /*error */
                    123:                msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
                    124:                return 0;
                    125:        }
                    126:        else { /* no error  */
                    127:                struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
                    128:                if ((int)(long)p==-1) { /* error */
                    129:                        msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
                    130:                        return 0;
                    131:                }
                    132:                return p;
                    133:        }
                    134: #else
                    135:        char buf[10];
                    136:        LPSECURITY_ATTRIBUTES psec=0;
                    137:        HANDLE shmid=0;
                    138:        SECURITY_DESCRIPTOR sd;
                    139:        SECURITY_ATTRIBUTES sa;
                    140:        snprintf(buf, sizeof(buf), "NTP%d", unit);
                    141:        if (unit >= 2) { /* world access */
                    142:                if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
                    143:                        msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
                    144:                        return 0;
                    145:                }
                    146:                if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
                    147:                        msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
                    148:                        return 0;
                    149:                }
                    150:                sa.nLength=sizeof (SECURITY_ATTRIBUTES);
                    151:                sa.lpSecurityDescriptor=&sd;
                    152:                sa.bInheritHandle=0;
                    153:                psec=&sa;
                    154:        }
                    155:        shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
                    156:                                 0, sizeof (struct shmTime),buf);
                    157:        if (!shmid) { /*error*/
                    158:                char buf[1000];
                    159:                FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
                    160:                               0, GetLastError (), 0, buf, sizeof (buf), 0);
                    161:                msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
                    162:                return 0;
                    163:        }
                    164:        else {
                    165:                struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid, 
                    166:                                                                    FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
                    167:                if (p==0) { /*error*/
                    168:                        char buf[1000];
                    169:                        FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
                    170:                                       0, GetLastError (), 0, buf, sizeof (buf), 0);
                    171:                        msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
                    172:                        return 0;
                    173:                }
                    174:                return p;
                    175:        }
                    176: #endif
                    177: }
                    178: /*
                    179:  * shm_start - attach to shared memory
                    180:  */
                    181: static int
                    182: shm_start(
                    183:        int unit,
                    184:        struct peer *peer
                    185:        )
                    186: {
                    187:        struct refclockproc *pp;
                    188:        struct shmunit *up;
                    189: 
                    190:        pp = peer->procptr;
                    191:        pp->io.clock_recv = noentry;
                    192:        pp->io.srcclock = (caddr_t)peer;
                    193:        pp->io.datalen = 0;
                    194:        pp->io.fd = -1;
                    195: 
                    196:        up = emalloc(sizeof(*up));
                    197:        memset(up, 0, sizeof(*up));
                    198:        pp->unitptr = (caddr_t)up;
                    199: 
                    200:        up->shm = getShmTime(unit);
                    201: 
                    202:        /*
                    203:         * Initialize miscellaneous peer variables
                    204:         */
                    205:        memcpy((char *)&pp->refid, REFID, 4);
                    206:        if (up->shm != 0) {
                    207:                up->shm->precision = PRECISION;
                    208:                peer->precision = up->shm->precision;
                    209:                up->shm->valid=0;
                    210:                up->shm->nsamples=NSAMPLES;
                    211:                pp->clockdesc = DESCRIPTION;
                    212:                return (1);
                    213:        }
                    214:        else {
                    215:                return 0;
                    216:        }
                    217: }
                    218: 
                    219: 
                    220: /*
                    221:  * shm_shutdown - shut down the clock
                    222:  */
                    223: static void
                    224: shm_shutdown(
                    225:        int unit,
                    226:        struct peer *peer
                    227:        )
                    228: {
                    229:        struct refclockproc *pp;
                    230:        struct shmunit *up;
                    231: 
                    232:        pp = peer->procptr;
                    233:        up = (struct shmunit *)pp->unitptr;
                    234: 
                    235:        if (NULL == up)
                    236:                return;
                    237: #ifndef SYS_WINNT
                    238:        /* HMS: shmdt()wants char* or const void * */
                    239:        (void) shmdt ((char *)up->shm);
                    240: #else
                    241:        UnmapViewOfFile (up->shm);
                    242: #endif
                    243:        free(up);
                    244: }
                    245: 
                    246: 
                    247: /*
                    248:  * shm_timer - called every second
                    249:  */
                    250: static  void
                    251: shm_timer(int unit, struct peer *peer)
                    252: {
                    253:        if (OLDWAY)
                    254:                return;
                    255: 
                    256:        shm_peek(unit, peer);
                    257: }
                    258: 
                    259: 
                    260: /*
                    261:  * shm_poll - called by the transmit procedure
                    262:  */
                    263: static void
                    264: shm_poll(
                    265:        int unit,
                    266:        struct peer *peer
                    267:        )
                    268: {
                    269:        struct refclockproc *pp;
                    270:        int ok;
                    271: 
                    272:        pp = peer->procptr;
                    273:        
                    274:        if (OLDWAY) {
                    275:                ok = shm_peek(unit, peer);
                    276:                if (!ok) return;
                    277:        }
                    278: 
                    279:         /*
                    280:          * Process median filter samples. If none received, declare a
                    281:          * timeout and keep going.
                    282:          */
                    283:         if (pp->coderecv == pp->codeproc) {
                    284:                 refclock_report(peer, CEVNT_TIMEOUT);
                    285:                shm_clockstats(unit, peer);
                    286:                 return;
                    287:         }
                    288:        pp->lastref = pp->lastrec;
                    289:        refclock_receive(peer);
                    290:        shm_clockstats(unit, peer);
                    291: }
                    292: 
                    293: /*
                    294:  * shm_peek - try to grab a sample
                    295:  */
                    296: int shm_peek(
                    297:        int unit,
                    298:        struct peer *peer
                    299:        )
                    300: {
                    301:        struct refclockproc *pp;
                    302:        struct shmunit *up;
                    303:        struct shmTime *shm;
                    304: 
                    305:        /*
                    306:         * This is the main routine. It snatches the time from the shm
                    307:         * board and tacks on a local timestamp.
                    308:         */
                    309:        pp = peer->procptr;
                    310:        up = (struct shmunit*)pp->unitptr;
                    311:        up->ticks++;
                    312:        if (up->shm == 0) {
                    313:                /* try to map again - this may succeed if meanwhile some-
                    314:                body has ipcrm'ed the old (unaccessible) shared mem segment */
                    315:                up->shm = getShmTime(unit);
                    316:        }
                    317:        shm = up->shm;
                    318:        if (shm == 0) {
                    319:                refclock_report(peer, CEVNT_FAULT);
                    320:                return(0);
                    321:        }
                    322:        if (shm->valid) {
                    323:                struct timeval tvr;
                    324:                struct timeval tvt;
                    325:                struct tm *t;
                    326:                int ok=1;
                    327:                tvr.tv_sec = 0;
                    328:                tvr.tv_usec = 0;
                    329:                tvt.tv_sec = 0;
                    330:                tvt.tv_usec = 0;
                    331:                switch (shm->mode) {
                    332:                    case 0: {
                    333:                            tvr.tv_sec=shm->receiveTimeStampSec;
                    334:                            tvr.tv_usec=shm->receiveTimeStampUSec;
                    335:                            tvt.tv_sec=shm->clockTimeStampSec;
                    336:                            tvt.tv_usec=shm->clockTimeStampUSec;
                    337:                    }
                    338:                    break;
                    339:                    case 1: {
                    340:                            int cnt=shm->count;
                    341:                            tvr.tv_sec=shm->receiveTimeStampSec;
                    342:                            tvr.tv_usec=shm->receiveTimeStampUSec;
                    343:                            tvt.tv_sec=shm->clockTimeStampSec;
                    344:                            tvt.tv_usec=shm->clockTimeStampUSec;
                    345:                            ok=(cnt==shm->count);
                    346:                    }
                    347:                    break;
                    348:                    default:
                    349:                        msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",shm->mode);
                    350:                }
                    351:                shm->valid=0;
                    352:                if (ok) {
                    353:                        time_t help;    /* XXX NetBSD has incompatible tv_sec */
                    354: 
                    355:                        TVTOTS(&tvr,&pp->lastrec);
                    356:                        pp->lastrec.l_ui += JAN_1970;
                    357:                        /* pp->lasttime = current_time; */
                    358:                        pp->polls++;
                    359:                        help = tvt.tv_sec;
                    360:                        t = gmtime (&help);
                    361:                        pp->day=t->tm_yday+1;
                    362:                        pp->hour=t->tm_hour;
                    363:                        pp->minute=t->tm_min;
                    364:                        pp->second=t->tm_sec;
                    365:                        pp->nsec=tvt.tv_usec * 1000;
                    366:                        peer->precision=shm->precision;
                    367:                        pp->leap=shm->leap;
                    368:                } 
                    369:                else {
                    370:                        refclock_report(peer, CEVNT_FAULT);
                    371:                        msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
                    372:                        up->clash++;
                    373:                        return(0);
                    374:                }
                    375:        }
                    376:        else {
                    377:                refclock_report(peer, CEVNT_TIMEOUT);
                    378:                up->notready++;
                    379:                return(0);
                    380:        }
                    381:        if (!refclock_process(pp)) {
                    382:                refclock_report(peer, CEVNT_BADTIME);
                    383:                up->bad++;
                    384:                return(0);
                    385:        }
                    386:        up->good++;
                    387:        return(1);
                    388: }
                    389: 
                    390: /*
                    391:  * shm_clockstats - dump and reset counters
                    392:  */
                    393: void shm_clockstats(
                    394:        int unit,
                    395:        struct peer *peer
                    396:        )
                    397: {
                    398:        struct refclockproc *pp;
                    399:        struct shmunit *up;
                    400:        char logbuf[256];
                    401: 
                    402:        pp = peer->procptr;
                    403:        up = (struct shmunit*)pp->unitptr;
                    404: 
                    405:        if (!(pp->sloppyclockflag & CLK_FLAG4)) return;
                    406: 
                    407:         snprintf(logbuf, sizeof(logbuf), "%3d %3d %3d %3d %3d",
                    408:                 up->ticks, up->good, up->notready, up->bad, up->clash);
                    409:         record_clock_stats(&peer->srcadr, logbuf);
                    410: 
                    411:        up->ticks = up->good = up->notready =up->bad = up->clash = 0;
                    412: 
                    413: }
                    414: 
                    415: #else
                    416: int refclock_shm_bs;
                    417: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>