diff -up ntp-4.2.6p5/ntpd/refclock_shm.c.nanoshm ntp-4.2.6p5/ntpd/refclock_shm.c --- ntp-4.2.6p5/ntpd/refclock_shm.c.nanoshm 2010-02-04 08:26:55.000000000 +0100 +++ ntp-4.2.6p5/ntpd/refclock_shm.c 2014-08-25 15:43:45.608698816 +0200 @@ -83,16 +83,18 @@ struct shmTime { * 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]; + volatile int count; + time_t clockTimeStampSec; + int clockTimeStampUSec; + time_t receiveTimeStampSec; + int receiveTimeStampUSec; + int leap; + int precision; + int nsamples; + volatile int valid; + unsigned clockTimeStampNSec; /* Unsigned ns timestamps */ + unsigned receiveTimeStampNSec; /* Unsigned ns timestamps */ + int dummy[8]; }; struct shmunit { @@ -320,31 +322,68 @@ int shm_peek( return(0); } if (shm->valid) { - struct timeval tvr; - struct timeval tvt; + struct timespec tvr; + struct timespec tvt; struct tm *t; int ok=1; + unsigned cns_new, rns_new; + int cnt; tvr.tv_sec = 0; - tvr.tv_usec = 0; + tvr.tv_nsec = 0; tvt.tv_sec = 0; - tvt.tv_usec = 0; + tvt.tv_nsec = 0; switch (shm->mode) { - case 0: { - tvr.tv_sec=shm->receiveTimeStampSec; - tvr.tv_usec=shm->receiveTimeStampUSec; - tvt.tv_sec=shm->clockTimeStampSec; - tvt.tv_usec=shm->clockTimeStampUSec; - } - break; - case 1: { - int cnt=shm->count; - tvr.tv_sec=shm->receiveTimeStampSec; - tvr.tv_usec=shm->receiveTimeStampUSec; - tvt.tv_sec=shm->clockTimeStampSec; - tvt.tv_usec=shm->clockTimeStampUSec; - ok=(cnt==shm->count); - } - break; + case 0: + tvr.tv_sec = shm->receiveTimeStampSec; + tvr.tv_nsec = shm->receiveTimeStampUSec * 1000; + rns_new = shm->receiveTimeStampNSec; + tvt.tv_sec = shm->clockTimeStampSec; + tvt.tv_nsec = shm->clockTimeStampUSec * 1000; + cns_new = shm->clockTimeStampNSec; + + /* Since these comparisons are between unsigned + ** variables they are always well defined, and any + ** (signed) underflow will turn into very large + ** unsigned values, well above the 1000 cutoff + */ + if ( ((cns_new - (unsigned)tvt.tv_nsec) < 1000) + && ((rns_new - (unsigned)tvr.tv_nsec) < 1000)) { + tvt.tv_nsec = cns_new; + tvr.tv_nsec = rns_new; + } + // At this point tvr and tvt contains valid ns-level + // timestamps, possibly generated by extending the + // old us-level timestamps + + break; + + case 1: + cnt = shm->count; + + tvr.tv_sec = shm->receiveTimeStampSec; + tvr.tv_nsec = shm->receiveTimeStampUSec * 1000; + rns_new = shm->receiveTimeStampNSec; + tvt.tv_sec = shm->clockTimeStampSec; + tvt.tv_nsec = shm->clockTimeStampUSec * 1000; + cns_new = shm->clockTimeStampNSec; + ok = (cnt == shm->count); + + /* Since these comparisons are between unsigned + ** variables they are always well defined, and any + ** (signed) underflow will turn into very large + ** unsigned values, well above the 1000 cutoff + */ + if ( ((cns_new - (unsigned)tvt.tv_nsec) < 1000) + && ((rns_new - (unsigned)tvr.tv_nsec) < 1000)) { + tvt.tv_nsec = cns_new; + tvr.tv_nsec = rns_new; + } + // At this point tvr and tvt contains valid ns-level + // timestamps, possibly generated by extending the + // old us-level timestamps + + break; + default: msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",shm->mode); } @@ -352,8 +391,8 @@ int shm_peek( if (ok) { time_t help; /* XXX NetBSD has incompatible tv_sec */ - TVTOTS(&tvr,&pp->lastrec); - pp->lastrec.l_ui += JAN_1970; + pp->lastrec.l_ui = (u_long)tvr.tv_sec + JAN_1970; + pp->lastrec.l_uf = tvr.tv_nsec * 4.294967296; /* pp->lasttime = current_time; */ pp->polls++; help = tvt.tv_sec; @@ -362,7 +401,7 @@ int shm_peek( pp->hour=t->tm_hour; pp->minute=t->tm_min; pp->second=t->tm_sec; - pp->nsec=tvt.tv_usec * 1000; + pp->nsec = tvt.tv_nsec; peer->precision=shm->precision; pp->leap=shm->leap; }