Date: Tue, 05 Feb 2002 12:45:02 +0100 From: Poul-Henning Kamp <phk@critter.freebsd.dk> To: John Polstra <jdp@polstra.com> Cc: hackers@FreeBSD.ORG, msmith@hub.freebsd.org Subject: Re: A question about timecounters Message-ID: <86051.1012909502@critter.freebsd.dk> In-Reply-To: Your message of "Mon, 04 Feb 2002 17:41:59 PST." <200202050141.g151fxW02520@vashon.polstra.com>
next in thread | previous in thread | raw e-mail | index | archive | help
In message <200202050141.g151fxW02520@vashon.polstra.com>, John Polstra writes: >Mike Smith <msmith@hub.freebsd.org> wrote: >> >> It's not necessarily caused by interrupt latency. Here's the assumption >> that's being made. >[...] > >Thanks for the superb explanation! I appreciate it. My apologies for never getting the timecounter paper finished and published, I should really do that... >That's the global variable named "timecounter", right? I did notice >one potential problem: that variable is not declared volatile. So >in this part ... This may be a problem, I have yet to see GCC make different code for that but I should probably have committed the "volatile" anyway. >I also noticed this in tco_forward(): > > tco = timecounter; > tc = sync_other_counter(); > [...] > if (tco->tc_poll_pps) > >But sync_other_counter() loads its own copy of "timecounter", >and there's no guarantee it hasn't changed from the value that >tco_forward() saved in its local variable. I'm not sure yet if >that's a potential problem. It could corrected by passing "tco" as >an argument to sync_other_counter. I'll try that too. This code is actually correct, the tc_poll_pps needs to be done on the "old" timecounter, because that would be the reference for any captured hardware timestamps, if I did it on the new timecounter I might get negative deltas which would complicate things. Also the new timecounter may have a changed frequency/offset (tickadj/ntpd and all that). >> There are a couple of possible problems with this mechanism. >> >> One is that the ring "catches up" with your saved copy of the >> "current" pointer, ie. inbetween fetching the pointer and reading the >> timecounter contents, the "next" pointer passes over you again in such >> a fashion that you get garbage out of the structure. This is unlikely. >> Another is that there is a race between multiple updaters of the >> timecounter; if two parties are both updating the "next" timecounter >> along with another party trying to get the "current" time, this could >> cause corruption. I have worries in this respect with SMPng, but have yet to see a corrupted timecounter ring. There is one more failure mode which you have overlooked: The individual timecounters maintain a binary counter of a certain width, if interrupt latency gets too bad, this may overflow. This is a non-issue for the TSC, which is 64bit wide in hardware. It should also be a non-issue for the PIIX which is at least 24 bits in hardware. But the i8254 is a piece of shit in this context, and due to circumstances (apm being enabled0 most machines end up using the i8254 by default. My (and I belive Bruce's) diagnosis so far is that most problems come from the i8254 timecounter. I made a commit recently which made the core-code more robust to bad interrupt jitter/latency, basically it would return timestamps with too many microseconds or nanoseconds because it only tried to roll over to seconds ones. Now it while()'s over that loop. Hope this helps... -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk@FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86051.1012909502>