File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / refclock_shm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 2 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>