Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Nov 1995 15:59:10 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        current@FreeBSD.ORG, phk@freefall.freebsd.org
Subject:   Re: pentiums, clocks and xntpd: a smoking gun...
Message-ID:  <199511260459.PAA15785@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>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



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