From owner-freebsd-current@FreeBSD.ORG Thu Jul 22 21:12:11 2004 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D1FC016A4CE; Thu, 22 Jul 2004 21:12:11 +0000 (GMT) Received: from freebsd3.cimlogic.com.au (adsl-20-121.swiftdsl.com.au [218.214.20.121]) by mx1.FreeBSD.org (Postfix) with ESMTP id E90FA43D55; Thu, 22 Jul 2004 21:12:10 +0000 (GMT) (envelope-from jb@cimlogic.com.au) Received: by freebsd3.cimlogic.com.au (Postfix, from userid 102) id 581926AC0E; Fri, 23 Jul 2004 07:12:09 +1000 (EST) Date: Fri, 23 Jul 2004 07:12:09 +1000 From: John Birrell To: Bruce Evans Message-ID: <20040722211209.GB34260@freebsd3.cimlogic.com.au> 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> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20040723014517.B2451@epsplex.bde.org> User-Agent: Mutt/1.4.2.1i cc: current@freebsd.org Subject: Re: nanosleep returning early X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Jul 2004 21:12:12 -0000 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