Skip site navigation (1)Skip section navigation (2)
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>