Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Jul 2012 18:02:28 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        Jim Harris <jimharris@FreeBSD.org>, src-committers@FreeBSD.org, svn-src-all@FreeBSD.org, Andriy Gapon <avg@FreeBSD.org>, Bruce Evans <brde@optusnet.com.au>, svn-src-head@FreeBSD.org
Subject:   Re: svn commit: r238755 - head/sys/x86/x86
Message-ID:  <20120726174611.N2603@besplex.bde.org>
In-Reply-To: <20120725173212.GN2676@deviant.kiev.zoral.com.ua>
References:  <201207242210.q6OMACqV079603@svn.freebsd.org> <500F9E22.4080608@FreeBSD.org> <20120725102130.GH2676@deviant.kiev.zoral.com.ua> <20120725233033.N5406@besplex.bde.org> <20120725173212.GN2676@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 25 Jul 2012, Konstantin Belousov wrote:

> On Thu, Jul 26, 2012 at 12:15:54AM +1000, Bruce Evans wrote:
>> On Wed, 25 Jul 2012, Konstantin Belousov wrote:
>> ...
>> Most uses in FreeBSD are for timecounters.  Timecounters deliver the
>> current time.  This is unrelated to whatever instructions haven't
>> completed when the TSC is read.  Except possibly when the time needs
>> to be synchronized across CPUs, and when the uncompleted instruction
>> is a TSC read.
>>
>>> For tsc test, this means that after the change RDTSC executions are not
>>> reordered on the single core among themself. As I understand, CPU has
>>> no dependency noted between two reads of tsc by RDTSC, which allows
>>> later read to give lower value of counter.
>>
>> Gak.  Even when they are in the same instruction sequence?  Even though
>> the TSC reads fixed registers and some other instructions in the sequence
>> between the TSC use these registers?  The CPU would have to do significant
>> register renaming to break this.
> As I could only speculate, I believe that any modern CPU executes RDTSC
> as at least two separate steps, one is read from internal counter, and
> second is the registers update. It seems that the first kind of action
> is not serialized. I have no other explanation for the Jim findings.

In a reply to your later mail (made earlier), I quoted the Athlon64
manual documenting this problem (everything except exactly where the
serialization is applied).  The delay is similar to what happens in
software if the thread is preempted between reading the hardware time
and using the result.  It doesn't help to serializing the read and
the use without serializing everything between, which costs more.
Most uses don't care about the delay (else they need more than
serialization to limit it).  But if we care then we might have to
use a slow new instruction like rdtscp to tell the hardware to care,
or add slow locking to uses of the result in software (needs more
than critical_enter() to stop fast interrupt handlers.  BTW,
binuptime() is supposed to work in fast interrupt handlers.  This
is fragile but useful).

>>> {
>>>
>>> +	rmb();
>>> 	return (rdtsc32());
>>> }
>>
>> Please don't pessimize this further.  The time for rdtsc went from 6.5
>> cycles on AthlonXP to 65 cycles on core2 (mainly for for
>> P-state-invariance hardware synchronization I think).  Pretty soon it
>> will be as slow as an HPET and heading towards an i8254.  Adding rmb()
>> only makes it 12 cycles slower on core2, but 16 cycles (almost 3 times)
>> slower on AthlonXP.
> AthlonXP does not look as interesting target for optimizations. Fom what I
> can find this is PIII-era CPU.

Since CPUs hit the frequency wall just after AthlonXP, it is almost
as fast as a single modern CPU.  Much faster than a modern CPU for rdtsc,
and already optimized.  Probably much faster than a PIII for systemy
things like rdtsc.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120726174611.N2603>