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;
}