[RFR]: 8187227: __m68k_cmpxchg() is not being used correctly

David Holmes david.holmes at oracle.com
Wed Sep 6 02:11:10 UTC 2017


Hi Adrian,

Not really a review but I was curious about this ...

On 5/09/2017 8:00 PM, John Paul Adrian Glaubitz wrote:
> Hi!
> 
> Please review the changeset in [1] which fixes the incorrect use of 
> __m68k_cmpxchg().
> 
> The description for this change is [2]:
> 
> =============================================================
> 
> On m68k, linux-zero has platform-specific implementations for 
> compare_and_swap(), add_and_fetch() and lock_test_and_set(). These 
> functions are all using __m68k_cmpxchg() which is basically a wrapper 
> around the m68k assembly instruction CAS.
> 
> Currently, all three functions make incorrect assumptions about how CAS 
> and its wrapper actually work and consequently use __m68k_cmpxchg() 
> incorrectly. The source code comment for __m68_cmpxchg() states:
> 
>    * Atomically store newval in *ptr if *ptr is equal to oldval for user 
> space.
>    * Returns newval on success and oldval if no exchange happened.
>    * This implementation is processor specific and works on
>    * 68020 68030 68040 and 68060.
> 
> However, looking at the documentation for the CAS instruction on m68k 
> [1] and the implementation of __m68k_cmpxchg(), this is actually not how 
> the function works. It does not return the update value on a successful 
> exchange but rather the contents the compare operand, i.e. oldval. If no 
> exchange happened, it will actually return the contents of the memory 
> location. newval is never returned and consequently testing for "newval" 
> in compare_and_swap(), add_and_fetch() and lock_test_and_set() is a bug.

I am surprised this even works at all. So trying to follow the logic if 
initially "prev == oldval" then the cas actually succeeds, but the loop 
logic thinks it failed and so retries. It re-reads the current value 
into prev, which no longer equals oldval, so the loop terminates and it 
returns "prev" which may actually be the value that was updated by the 
successful cas; or it could be a different value if some other thread 
has since also performed a successful cas. So this function would always 
report failure, even on success (except in ABA situation)! I can't see 
how anything would work in that case ??

BTW m68k_compare_and_swap does not need to have a loop at all, it only 
has to do the cas and return the correct value. A loop would only be 
needed if the low-level cas can fail spuriously - which does not seem to 
be the case.

Cheers,
David

> I have preapred a patch that fixes this issue by making correct use of 
> __m68k_cmpxchg() in compare_and_swap(), add_and_fetch() and 
> lock_test_and_set(). This patch has been tested to work on Debian m68k.
> 
>> [1] http://68k.hax.com/CAS
> 
> =============================================================
> 
>> [1] http://cr.openjdk.java.net/~glaubitz/8187227/webrev.01/
>> [2] https://bugs.openjdk.java.net/browse/JDK-8187227
> 


More information about the hotspot-dev mailing list