Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Jul 1997 01:30:01 -0700 (PDT)
From:      Bruce Evans <bde@zeta.org.au>
To:        freebsd-bugs
Subject:   Re: kern/4112: Re: PPSCLOCK kernel diffs
Message-ID:  <199707280830.BAA17961@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/4112; it has been noted by GNATS.

From: Bruce Evans <bde@zeta.org.au>
To: FreeBSD-gnats-submit@FreeBSD.ORG, leres@ee.lbl.gov
Cc:  Subject: Re: kern/4112: Re: PPSCLOCK kernel diffs
Date: Mon, 28 Jul 1997 18:18:29 +1000

 >	Appended are context diffs to the 2.2.2-RELEASE kernel that
 >	add the PPSCLOCK option. Although the system already has
 >	the ability to capture DCD timestamps, the existing code
 >	suffers from several problems. First, the timestamp is not
 >	taken as soon as possible; measurements show that 2-3
 >	microseconds are lost on a really fast system like a 200
 >	MHz pentium pro.
 
 The latency is presumably because serial i/o or just checking for it
 takes some time, and DCD is checked after input.  This time doesn't
 depend much on the CPU - the (lack of) speed of i/o instructions
 depends more on the bus than on the CPU.  I don't think it is
 reasonable to attempy to support a latency of 2-3 microseconds in a
 general purpose driver or system.  While the "fast interrupt handler"
 interface used by the sio driver gives it a chance of reaching such a
 latency, there is no chance of reaching it consistently unless there
 is only one active device with a fast interrupt handler in the whole
 system.  Another active 16550A device (even on the same interrupt)
 would give up to about 75 usec of jitter, because it takes up to about
 60 i/o instructions to handle one interrupt (more for the COM_MULTIPORT
 configuration), and each i/o instruction takes up to about 1.25 usec.
 The jitter can be reduced to about 10 usec per extra active 16550A
 device by not using the FIFO.
 
 I have some improvements to the interrupt handler that would get
 in the way of polling the modem status first.  They depend on the
 UART actually working, so that the modem status doesn't need to be
 polled unless it has changed.  The UART doesn't tell you that the
 modem status register should be read until you have processed what
 the UART considers to be higher priority events.
 
 >	2nd, the lack of a event serial number
 >	makes it impossible to detect extra or missing pulses.
 
 OK.
 
 >	The current layout has a new include file, sys/ppsclock.h.
 >	It might be a better idea to move the contents of this file
 >	into sys/ttycom.h and rename the two new ioctls so they
 >	fit in with the other TIO* ioctls.
 
 Do you want the whole LBL copyright on the merged version?
 
 >+ #ifdef PPSCLOCK
 >+ 		/*
 >+ 		 * Check the modem status now so we get a better
 >+ 		 * timestamp (On a 200 MHZ Pentium Pro this makes
 >+ 		 * a difference of about 2 or 3 microseconds...)
 >+ 		 *
 >+ 		 * If data carrier detect changed and it was the
 >+ 		 * one we are waiting for (either leading or trailing
 >+ 		 * edge) then grab the timestamp.
 >+ 		 */
 >+ 		modem_status = inb(com->modem_status_port);
 >+ 		if (com->do_pps_timestamp &&
 >+ 		    ((modem_status ^ com->last_modem_status) & MSR_DCD) != 0 &&
 >+ 		    com->pps_tet ^ ((modem_status & MSR_DCD) != 0)) {
 >+ 			microtime(&com->ppsclock.tv);
 >+ 			++com->ppsclock.serial;
 >+ 		}
 >+ #endif
 
 This inherits a bug from the old code.  I somehow convinced myself that it's
 OK to call microtime() from here.  It's not.  microtime() can only be called
 from ordinary interrupt handlers.  Calling it from fast interrupt handlers
 may fail because of the following problems:
 
 1. If microtime() uses the i8254 counter and not the "i586" TSC, then a
    clock overflow heuristic is used.  The heuristic is fine-tuned to
    work at an i8254 clock interrupt period of 62.5 usec, and won't
    work if clock interrupts have been disabled for more than about
    TIMER0_LATCH_COUNT = 20 i8254 cycles (17 usec).  Fast interrupt
    handlers often break this by keeping all interrupts disabled for
    100 usec or so.
 
 2. `time' is not valid in fast interrupt handlers, since the fast interrupt
    handler may have interrupted hardclock().  Therefore, the accesses to
    `time' in microtime() are invalid if microtime() is called from
    a fast interrupt handler.  Note that the feature of fast interrupt
    handlers that causes this problem - that they can interrupt any normal
    interrupt handler - is the same feature that gives you a chance of
    getting very accurate timestamps.  Also, the complications for the
    kernel PLL and PPSCLOCK in hardclock() make this nontrivial to fix
    - for a simple adjustment to `time' it would only be necessary to
    disable fast interrupts while doing the adjustment and to somehow
    keep track of the before and after states so that microtime() knows
    which one to use.  In fact, the simple adjustment to `time' is
    already handled correctly for the TSC case in cpu_clockupdate().
    Perhaps this case already works, because other adjustments are
    smaller than interrupt jitter.
 
 John Hay tried calling hardpps() from siointr1().  I don't like this,
 because hardpps() is probably too slow on slow machines.
 
 Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199707280830.BAA17961>