From owner-freebsd-current Sat Feb 16 23:51:28 2002 Delivered-To: freebsd-current@freebsd.org Received: from mailman.zeta.org.au (mailman.zeta.org.au [203.26.10.16]) by hub.freebsd.org (Postfix) with ESMTP id 125F637B431 for ; Sat, 16 Feb 2002 23:51:10 -0800 (PST) Received: from bde.zeta.org.au (bde.zeta.org.au [203.2.228.102]) by mailman.zeta.org.au (8.9.3/8.8.7) with ESMTP id SAA18981; Sun, 17 Feb 2002 18:51:00 +1100 Date: Sun, 17 Feb 2002 18:54:13 +1100 (EST) From: Bruce Evans X-X-Sender: To: Matthew Dillon Cc: Subject: Re: 'microuptime() went backwards ...' using ACPI timer. Shouldn't that be impossible? In-Reply-To: <200202170028.g1H0SQZ41827@apollo.backplane.com> Message-ID: <20020217184436.M934-100000@gamplex.bde.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On Sat, 16 Feb 2002, Matthew Dillon wrote: > Testing with a 'make -j 10 buildworld' on a -current box I am getting > regular: > > microuptime() went backwards (146.826785 -> 146.156715) > microuptime() went backwards (146.826782 -> 146.228636) > ... > microuptime() went backwards (8945.938288 -> 8945.251603) > microuptime() went backwards (8945.938306 -> 8945.347173) > microuptime() went backwards (9142.847550 -> 9142.847546) > > This occurs both with and without the gettimeofday Giant-removal patch, so > I am fairly sure it has nothing to do with any of my current work. This is > running -current on a DELL2550 (2xCPUs), compiled with the SMP option. The fact that the timecounter usually goes backwards by about 0.68 seconds is probably significant, but I can't quite explain it. > Timecounter "i8254" frequency 1193182 Hz > ... > Timecounter "ACPI" frequency 3579545 Hz > acpi_timer0: <32-bit timer at 3.579545MHz> port 0x808-0x80b on acpi0 > acpi_cpu0: on acpi0 > acpi_cpu1: on acpi0 > acpi_pcib0: on acpi0 > ... > > Question: How can this be occuring at all? Isn't the ACPI counter a > 32 bit counter that does not have the rollover problems that the 8254 timer > has? Timecounters go backwards when the timecounter update or reference code is called insufficiently often to prevent overflow. The rollover problems of the i8254 timecounter actually reduce this problem. If an i8254 rollover is missed, then it causes the the i8254 timecounter to go forward less than it should. I just wrote the following fix for some of the overflow problems. %%% Index: kern_tc.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_tc.c,v retrieving revision 1.113 diff -c -2 -r1.113 kern_tc.c *** kern_tc.c 7 Feb 2002 21:21:55 -0000 1.113 --- kern_tc.c 17 Feb 2002 06:25:14 -0000 *************** *** 108,114 **** struct timecounter *tc; ! tc = timecounter; ! *bt = tc->tc_offset; ! bintime_addx(bt, tc->tc_scale * tco_delta(tc)); } --- 95,129 ---- struct timecounter *tc; ! /* ! * The loop is to handle changes of timecounter underneath us. ! * Such changes may even become normal for preemptive kernels. ! * It is quite reasonable for idle priority processes to not ! * run for many seconds, and if they are not running after ! * being preempted here, the timecounter may cycle many times ! * underneath them. An NTIMECOUNTER of > 2 is neither necessary ! * or sufficient for fixing this problem, unless NTIMECOUNTER is ! * preposterously large. NTIMECOUNTER == 2 suffices for most ! * cases, and something more is required to fix the general case. ! * ! * I hope this also fixes problems with overflow of the ! * multiplication. We depend on tc not becoming stale by more ! * than 1 second. We will now normally see such staleness ! * because it will cause the timecounter to change many times ! * underneath us. There will only be problems if hardclock() ! * doesn't run for many seconds, but hardclock() is a very ! * high priority interrupt, so such problems "can't happen". ! * ! * XXX should use a generation count. ! * ! * XXX problems with hardclock() can happen, e.g., at boot time ! * if you have fixed hardclock() to not be a broken fast interrupt ! * handler, or if you sit at the ddb prompt for several seconds. ! * Should do something to make them harmless. ! */ ! do { ! tc = timecounter; ! *bt = tc->tc_offset; ! bintime_addx(bt, tc->tc_scale * tco_delta(tc)); ! } while (tc != timecounter); } %%% Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message