From: Linus Torvalds on


On Wed, 17 Feb 2010, Zachary Amsden wrote:
>
> The x86 instruction set provides the ability to add an additional
> bit into addition or subtraction by using the carry flag.
> It also provides instructions to directly set or clear the
> carry flag. By forcibly setting the carry flag, we can then
> represent one particular 64-bit constant, namely
>
> 0xffffffff + 1 = 0x100000000
>
> using only 32-bit values. In particular we can optimize the rwsem
> write lock release by noting it is of exactly this form.

Don't do this.

Just shift the constants down by two, and suddenly you don't need any
clever tricks, because all the constants fit in 32 bits anyway,
regardless of sign issues.

So just change the

# define RWSEM_ACTIVE_MASK 0xffffffffL

line into

# define RWSEM_ACTIVE_MASK 0x3fffffffL

and you're done.

The cost of 'adc' may happen to be identical in this case, but I suspect
you didn't test on UP, where the 'lock' prefix goes away. An unlocked
'add' tends to be faster than an unlocked 'adc'.

(It's possible that some micro-architectures don't care, since it's a
memory op, and they can see that 'C' is set. But it's a fragile assumption
that it would always be ok).

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: H. Peter Anvin on
On 02/17/2010 02:10 PM, Linus Torvalds wrote:
>
>
> On Wed, 17 Feb 2010, Zachary Amsden wrote:
>>
>> The x86 instruction set provides the ability to add an additional
>> bit into addition or subtraction by using the carry flag.
>> It also provides instructions to directly set or clear the
>> carry flag. By forcibly setting the carry flag, we can then
>> represent one particular 64-bit constant, namely
>>
>> 0xffffffff + 1 = 0x100000000
>>
>> using only 32-bit values. In particular we can optimize the rwsem
>> write lock release by noting it is of exactly this form.
>
> Don't do this.
>
> Just shift the constants down by two, and suddenly you don't need any
> clever tricks, because all the constants fit in 32 bits anyway,
> regardless of sign issues.
>

Why bother at all? I thought it mattered when I saw __downgrade_write()
as an inline, but in fact it is only ever used inside the
downgrade_write() out-of-line function, so we're talking about saving
*five bytes* across the whole kernel in the best case. I vote for
leaving it the way it is, and get the very slight extra readability.
There is no point in moving bits around, either.

-hpa
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: H. Peter Anvin on
On 02/17/2010 02:10 PM, Linus Torvalds wrote:
>
> The cost of 'adc' may happen to be identical in this case, but I suspect
> you didn't test on UP, where the 'lock' prefix goes away. An unlocked
> 'add' tends to be faster than an unlocked 'adc'.
>
> (It's possible that some micro-architectures don't care, since it's a
> memory op, and they can see that 'C' is set. But it's a fragile assumption
> that it would always be ok).
>

FWIW, I don't know of any microarchitecture where adc is slower than
add, *as long as* the setup time for the CF flag is already used up.
However, as I already commented, I don't think this is worth it. This
inline appears to only be instantiated once, and as such, it takes a
whopping six bytes across the entire kernel.

-hpa

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Zachary Amsden on
>
> On 02/17/2010 02:10 PM, Linus Torvalds wrote:
>
>> The cost of 'adc' may happen to be identical in this case, but I suspect
>> you didn't test on UP, where the 'lock' prefix goes away. An unlocked
>> 'add' tends to be faster than an unlocked 'adc'.
>>
>> (It's possible that some micro-architectures don't care, since it's a
>> memory op, and they can see that 'C' is set. But it's a fragile assumption
>> that it would always be ok).
>>
>>
> FWIW, I don't know of any microarchitecture where adc is slower than
> add, *as long as* the setup time for the CF flag is already used up.
> However, as I already commented, I don't think this is worth it. This
> inline appears to only be instantiated once, and as such, it takes a
> whopping six bytes across the entire kernel.
>
>

Without the locks,

stc; adc %rdx, (%rax)

vs.

add %rdx, (%rax)

Shows no statistical difference on Intel.
On AMD, the first form is about twice as expensive.

Course this is all completely useless, but it would be if the locks were
inline (which is actually an askable question now). There was just so
much awesomeness going on with the 64-bit rwsem constructs I felt I had
to add even more awesomeness to the plate. For some definition of
awesomeness.

Zach
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Linus Torvalds on


On Wed, 17 Feb 2010, H. Peter Anvin wrote:
>
> FWIW, I don't know of any microarchitecture where adc is slower than
> add, *as long as* the setup time for the CF flag is already used up.

Oh, I think there are lots.

Look at just about any x86 latency/throughput table, and you'll see:

- adc latencies are typically much higher than a single cycle

But you are right that this is likel not an issue on any out-of-order
chip, since the 'stc' will schedule perfectly.

- but adc _throughput_ is also typically much higher, which indicates
that even if you do flag renaming, the 'adc' quite likely only
schedules in a single ALU unit.

For example, on a Pentium, adc/sbb can only go in the U pipe, and I think
the same is true of 'stc'. Now, nobody likely cares about Pentiums any
more, but the point is, 'adc' does often have constraints that a regular
'add' does not, and there's an example of a 'stc+adc' pair would at the
very least have to be scheduled with an instruction in between.

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/