Date: Sat, 1 May 2004 05:01:36 -0500 (CDT) From: Mike Silbersack <silby@silby.com> To: Bruce Evans <bde@zeta.org.au> Cc: John Baldwin <jhb@FreeBSD.org> Subject: Re: cvs commit: src/sys/i386/isa clock.c Message-ID: <20040501044209.L704@odysseus.silby.com> In-Reply-To: <20040501155815.L19822@gamplex.bde.org> References: <200404272003.i3RK3RFZ048001@repoman.freebsd.org> <20040430221434.J749@odysseus.silby.com> <20040501155815.L19822@gamplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 1 May 2004, Bruce Evans wrote: > The TSC calibration is lower level than the bug fixed in the commit. > It just uses DELAY(1000000) without even adjusting for DELAY()'s > overhead. Perhaps acpi is working "better" and throttling the cpu > during the calibration, or something is interrupting the calibration. > I hope FreeBSD still has interrupts disabled at that point, but there > may be SMM interrupts especially with acpi. Ok, I've read through the calibration code + DELAY now, and I see how much the i8254 stinks. But still, there's one piece of DELAY that seems suspicious to me: delta = prev_tick - tick; prev_tick = tick; if (delta < 0) { delta += timer0_max_count; /* * Guard against timer0_max_count being wrong. * This shouldn't happen in normal operation, * but it may happen if set_timer_freq() is * traced. */ if (delta < 0) delta = 0; } ticks_left -= delta; So this says to me that if timer wraps and we miss it, we assume that an entire cycle has passed. However, suppose that on our given machine that we take 5 counter ticks to run through this loop. In that case, if we last read the counter when it was at 4, we'd then read it again at 65535, and fall into the if statement. We'd then be subtracting timer0_max_count from ticks_list, when we really should have subtracted 5! Wouldn't be it be more accurate to restructure the code as follows? delta = prev_tick - tick; if (delta < 0) { delta += tick; } prev_tick = tick; ticks_left -= delta; This assumes that if we missed reading the count before it looped probably only missed it by a small amount, rather than by a large amount. On my Athlon 1800+ this changes CPU: AMD Athlon(tm) XP 1800+ (1526.85-MHz 686-class CPU) to CPU: AMD Athlon(tm) XP 1800+ (1527.00-MHz 686-class CPU) And when run with the troublesome Mobile Celeron 1.6G: CPU: Mobile Intel(R) Celeron(R) CPU 1.60GHz (797.19-MHz 686-class CPU) Wow! I think there's something wrong with my patch. :) And more seriously, I guess the wrapping case is happening A LOT! Could we possibly look at how many interrupts have happened during the wrapping in order to make this part of DELAY more accurate? The code that's present in the code above seems just as wrong as my patch does. Mike "Silby" Silbersack
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040501044209.L704>