From owner-freebsd-current Sat Nov 25 21:09:17 1995 Return-Path: owner-current Received: (from root@localhost) by freefall.freebsd.org (8.6.12/8.6.6) id VAA12315 for current-outgoing; Sat, 25 Nov 1995 21:09:17 -0800 Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by freefall.freebsd.org (8.6.12/8.6.6) with ESMTP id VAA12306 for ; Sat, 25 Nov 1995 21:09:00 -0800 Received: (from bde@localhost) by godzilla.zeta.org.au (8.6.9/8.6.9) id PAA15785; Sun, 26 Nov 1995 15:59:10 +1100 Date: Sun, 26 Nov 1995 15:59:10 +1100 From: Bruce Evans Message-Id: <199511260459.PAA15785@godzilla.zeta.org.au> To: current@FreeBSD.ORG, phk@freefall.freebsd.org Subject: Re: pentiums, clocks and xntpd: a smoking gun... Sender: owner-current@FreeBSD.ORG Precedence: bulk >I hooked a DCF77 receiver up to my Pentium/133 and here is my findings: >My microtime() drifts at a rate of: > (7.679466-5.081014)/(76710.567-75815.162) = .002901 >this is ten and a half second per hour :-( >It is surprisingly close to the ratio of: > (133.333333-133)/133 = .002506 >If this was the case, then my residual drift would be .000395, >or one and a half second per hour. Upgrade to a Pentium/100 ;-). Print the clock frequency in calibrate_cyclecounter() before dividing by 1000000. The 8254 clock may be a bit more accurate than 2901 ppm. The ones on my main systems are accurate to about +700 ppm and -300 ppm. I think the correct fix to these problems is: Pentium clock: 1. Increase the resolution of pentium_mhz. Either store it in hz and calculate: delta_usec = (delta_TSC * 1000000) / pentium_hz (ensure that delta_TSC is small so that this doesn't overflow) or store it in fixed point and calculate: delta_usec = (delta_TSC * frac) >> shift; 2. Implement `sysctl -w pentium_hz=value' or the fixed point version of this. 3. For each system, determine the best value for pentium_hz and set it in /etc/rc using sysctl. 8254 clock: 4.-6. Same as 1.-3. except for the 8254 clock instead of the Pentium clock. 7. Implement `sysctl -w timer0_max_count=value'. 8. For each system, determine the best value for timer0_max_count and set it in /etc/rc using sysctl. Do this even on Pentiums to make the clock interrupt frequency as close as possible to `hz'. General: 9. Make microtime() aware of adjustments to the clock. This involves scaling microtime()'s clock by ((tick + tickdelta) / tick) and perhaps adding the phase adjustment. 10. Implement a private version of `time_adj' and a sysctl to set it. The point of this is to handle lost resolution due to the value returned by CPU_THISTICKLEN() being measured in usec. The phase adjustment could be kept track of in CPU_THISTICKLEN() but it seems better to use the existing phase adjustment code in hardclock(). 11. For each system, determine the best value for the private `time_adj' and set it in /etc/rc using sysctl. Bruce