Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Jul 2004 07:12:09 +1000
From:      John Birrell <jb@cimlogic.com.au>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        current@freebsd.org
Subject:   Re: nanosleep returning early
Message-ID:  <20040722211209.GB34260@freebsd3.cimlogic.com.au>
In-Reply-To: <20040723014517.B2451@epsplex.bde.org>
References:  <20040721081310.GJ22160@freebsd3.cimlogic.com.au> <20040721220405.Y2346@epsplex.bde.org> <20040721215940.GK22160@freebsd3.cimlogic.com.au> <20040722225952.S1704@epsplex.bde.org> <20040723014517.B2451@epsplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jul 23, 2004 at 02:25:16AM +1000, Bruce Evans wrote:
> Now I think I know the reason.  The interval between clock interrupts
> is supposed to be 1/HZ seconds = `tick' microseconds, but it cannot
> be set nearly that precisely, and the imprecision of inversely
> proportional to HZ.  The i8254 counter has a default nominal frequency
> of 1193182 Hz.  Suppose that this is perfectly accurate.  Then to
> implement clock interrupts at HZ hz, we want to program the i8254's
> maximum count to 1193182/HZ in infinite precision, but counts must be
> integers so we must round.  The loss of precision is quite large for
> HZ = 1000: 1193182 / 1000.0 = 1193.182; rounding this (to nearest)
> gives 1193 and an error of 182 in 1193182 = 152 ppm.  Also, the extra
> tick added by tvtohz() is only 1000 uS long, so it only has a chance
> of about 152/1000 to compensate for the rounding error.  Finally, the
> explicit check that the interval has elapsed cannot compensate for
> errors larger than tc_tick/HZ because getnanouptime() is fuzzy.
> 
> Rounding 1193.182 to nearest happens to round down; thus clock ticks
> are shorter than `tick' microseconds, tvtohz()'s value is too small,
> and nanosleep() may return too early.  The loop limits the error to
> about 1 tick in this case.  The i8254 frequency may be calibrated or
> set using sysctl to a more (or less) accurate value.  Then the rounding
> may go the other way so that tvtohz()'s value is too large and nanoleep()
> may return too late.  The loop cannot limit the error in this case.
> The absolute error may be large for long sleeps.  E.g., 152 ppm over
> 1 day is 13 seconds.
> 
> tvtohz()'s value  may also be too large because the i8254 frequency
> is not known accurately.  It's nominal value is wrong by 10-100 Hz
> on my systems.  I minimize errors from this by calibrating all
> timecounters using a common clock.

Thanks for taking the trouble to explain this. 8-)

-- 
John Birrell



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