Blame SOURCES/ntp-4.2.6p5-nanoshm.patch

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