DragonflyBSD kernel clock improvements

Bruce Evans bde at zeta.org.au
Sun Jan 25 00:53:39 PST 2004

On Sat, 24 Jan 2004, Poul-Henning Kamp wrote:

> In message <200401241948.i0OJmDpo036688 at apollo.backplane.com>, Matthew Dillon w
> rites:
> >    There are a couple of things going on here... it isn't all just fluff.
> >
> >    First, the basic problem is that nanosleep() (aka sleep() aka
> >    usleep()) consistently sleeps for far longer then the requested time.
> I think this was subject to Brucification last it was raised on our
> lists.

Do you mean "subject to getting the details right"?

[Some context recovered]
> >    Second, the fractional compensation code for the 8254.  The 8254 runs
> >    at 1193182 Hz.  If your 'hz' is set to 100, a fixed clock reload value
> >    of 11931 looses significant precision.  The higher your 'hz' setting,
> >    the more precision is lost and the greater the error verses real time.

(The rounding is actually to nearest so 1193182 / 100 is rounded to
11932, not 11931.)  1193182 is only a nominal frequency.  On machines
I'm running right now, the actual frequency is 1193202, 1193211 and
1193276 (+-2 most days).  So using the default of 11932 loses quite a
bit to both accuracy and precision.  However, small errors are unimportant
in most or all applications, and the accuracy is easy to fix using
"sysctl machdep.i8254_freq=whatever".  I set all my clocks using the
relevant sysctl so that they are all as accurate as possible.  For the
i8254 clock, the best possible is 0.5 / 1193182 seconds or about 0.5
ppm, since fractional frequencies can't be set.  0.5 ppm is a good
practical accuracy to aim for since the frequencies of all clocks on
all my machines drift with the temperature by about +- 2 ppm every
day.  I try for 0.1 ppm long term accuracy using the TSC timecounter
and only use other timecounters for testing.

> >    If you are using the 8254 as your wallclock, then you will see a
> >    significant 'speed up' of the wall clock at higher hz settings.

> Unless you have replaced timecounters this is not true.  Timecounters
> are insensitive to how your Hz ticks, as long as it does it often
> enough.  (You should probably pull in the code from -current though,
> the 4.x code has some marginal issues).
> >    hz will wind up being far higher then the true frequency you
> >    requested.  It isn't just jitter... it's a permanent error factor and
> >    it can create significant problems if you are running ntpd.
> Only if you replaced timecounters.

Indeed.  The long-term drift from lost precision in scaling 1193182 by
HZ is zero, and the long-term drift from 1193182 being accurate is
whatever it is (can be quite large).  After fixing the inaccuracy as
above, the long-term drift due to innacuracy is significantly smaller
than the combination of short-term drifts due to nondeterministic
temperature.  ntp can handle innacuracy well enough (better than it
can handle short-term drifts) provided it is not too large (too large
is hundreds of ppm).

Short-term innaccuracy and imprecision is seen mainly by select() and
related timeouts, but it doesn't really matter in most cases since it
doesn't (or shouldn't) get a chance to build up.  E.g., if there is an
off-by-1 error setting the i8254 maxiumum count, then the period between
timeouts will be wrong by about 1 usec (1/1193182).  1 usec just doesn't
matter even on a pseudo-real-time system because interrupt latency is
more than that even without -current's pessimization of interrupts.
The inaccuracy can build up in some cases, but not in places like
nanotime() which don't simply count off a number of ticks.  nanotime()'s
innacuracy has differenct sources.

> >    Third, if you are not using the 8254 for your wallclock there will be
> >    persistent drift between clocks based on the 8254's hz-based interface
> >    (ticks) and clocks based on realtime.  The PLL part of the fix simply
> >    compensates for the 8254's constant drift relative to the wallclock
> >    by occassionally adding one or subtracting one from the 8254's reload
> >    value.
> This is harmless but IMO also pointless.

Setting the frequencies of all the clocks as above gives this to within
the precision of the frequency setting.  Synchronizing the frequencies
is useful mainly for testing.  It's annoying for ntp to see large
changes in the drift when you switch the timecounter.  Keeping the
nominal frequencies of all the clocks relatively correct to within 0.5
ppm limits the drift to this amount and ntp can't tell the difference
between this and a drift from temperature changes.


More information about the freebsd-current mailing list