Subject: NetBSD PPS vs FreeBSD PPS
To: None <tech-kern@NetBSD.ORG>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-kern
Date: 03/27/1998 17:01:11
I'm starting this as a new thread, for discussion of some oncrete,
fully fleshed, worked-out changes, proposd for immmediate or very
short-term incorporation into the NetBSD kernel.

Rationale:
The goal  is to get NetBSD's kernel support for high-precision
timekeeping up to a par with FreeBSD and Linux.  Currently, both those
kernels have strictly greater functionality than NetBSD.  They both
have kernel support for a feature called `pulse-per-second', or PPS.

PPS support means catching the edge of the PPS pulse from a radio (or
an atomic clock), timestamping it, and providing the timestamp to
either a user-level NTP daemon or in-kernel clock disciplining code,
which, in essence, interprets the PPS as an absolute second marker and
disciplines the local time-of-day clock to the PPS tick.  Till fairly
recently, this has been been a "niche" market, but with GPS OEM kits
and PPS kits available for under $400, microsecond accuracy to atomic
time can be had on a Unix box.

The following patch is, (with any necessary corrections) is all that's
needed to add kernel PPS support to NetBSD's com.c serial driver.  It
uses the same API provided by FreeBSD and Linux. The necessary
user-level support is already implemented by the xntpd code in our
tree.  the rest of the necessary machinery is in our tree.

But first I need some help with one line, marked below:

Index: com.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/com.c,v
retrieving revision 1.143
diff -c -r1.143 com.c
*** com.c	1998/03/22 00:55:37	1.143
--- com.c	1998/03/26 02:47:39
***************
*** 603,608 ****
--- 603,609 ----
  		com_modem(sc, 0);
  		(void) tsleep(sc, TTIPRI, ttclos, hz);
  	}
+ 	sc->sc_dcd_timestamping = 0;
  
  	/* Turn off interrupts. */
  #ifdef DDB
***************
*** 933,938 ****
--- 934,943 ----
  		*(int *)data = bits;
  		break;
  	}
+ 	case TIOCDCDTIMESTAMP:
+ 		com->sc_dcd_timestamping = 1;
+ 		*(struct timeval *)data = com->dcd_timestamp;
+ 		break;
  	default:
  		error = ENOTTY;
  		break;
***************
*** 1749,1754 ****
--- 1754,1763 ----
  		sc->sc_msr = msr;
  		if (ISSET(delta, sc->sc_msr_mask)) {
  			SET(sc->sc_msr_delta, delta);
+ 
+ 			if (sc->sc_dcd_timestamping && ISSET(delta, MSR_DCD)) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 				microtime(&sc->sc_dcd_timestamp);
+ 			}
  
  			/*
  			 * Stop output immediately if we lose the output
Index: comvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/comvar.h,v
retrieving revision 1.22
diff -c -r1.22 comvar.h
*** comvar.h	1998/02/02 23:01:05	1.22
--- comvar.h	1998/03/26 02:55:02
***************
*** 109,114 ****
--- 109,117 ----
  	void (*disable) __P((struct com_softc *));
  	int enabled;
  
+ 	int	sc_dcd_timestamping;		/* boolean flag */
+ 	struct timeval	sc_dcd_timestamp;
+ 
  #if NRND > 0 && defined(RND_COM)
  	rndsource_element_t  rnd_source;
  #endif


The marked line is trying to test for carrier transition and do the
timestamp only once per transition.  It's jut a guess, and it's
probably wrong. I'm asking for help to get it fixed.

For about the eight time, I would really, really appreciate
if Charles Hannum could take a look at this; he's the expert.

once fixed, the concrete proposal is:

      1.  The API in this patch  should not be changed.  Nobody
	  here likes it much, but it's ``the standard''  which
	  xntpd expects and its' what FreeBSD and Linux already implement.
	  Style fixes  that  dont change the API to xntpd would be great.

	  A new, cleaner API can be added but the old one has to stay
	  until the xntpd maintainers are persauded to support an
	  alternative.

      2. I'd  like to commit the patch once its beleived to be
         functionally correct and meets Charles Hannum's approval.
	 I beleive Bill studenmund is looking at similiar
	 patches for the MI zs driver.

      3. If at all possible, I'd like to see The NetBSD foundation
         running a publically available NTP sevice with in-kernel
	 PPS support. (i.e,. this patch). Preferably on an i386.
	 We already have one tentaive offer for an existing, well-located
	 NTP server.

	 NTP is carefully engineered to be very sensitive. If we can
	 get a high-stability server running and measure exactly what
	 its interrupt latency is, we can *prove* that NetBSD is as
	 least as good as itss competitors at certain highly
	 performance-sensitive appiclations.  We can quote the latency
	 measured by NetBSD users with GPS clocks to anyone
	 who disparages NetBSD's interrupt performance. 
 	 It would be Cool.  It would be a great aid in getting
	 really accurate timing measurements for performance tuning.
	 and so on.

      4. I'd also like to add

	 #ifdef  PPS_SYNC
		  hardpps(&sc->sc_dcd_timestamp, sc->sc_dcd_timestamp.tv_usec)
         #endif

	which is not   quite the right semantics, but lets
	anyone who wants turn on the in-kernel support for
	disciplining the CPU real-time ckock directly from
	the PPS signal. But this is entirely optional.

And another reminder: this has *absolutely nothing* to do with the
other concurrent thread, which is discussing speculative ways to
handle non-PPS clocks with, at best, an accuracy of a few tens of
milliseconds. With a good GPS clock, this code should be able to get
to under 10 microseconds. Please don't confuse the two any more.