Annotation of embedaddon/ntp/ntpd/refclock_shm.c, revision 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>