Blob Blame History Raw
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;
 		}