On Thu, Mar 24, 2022 at 09:28:15AM +0100, Tom de Vries via Gcc-patches wrote:
> Hi,
> 
> On nvptx (using a Quadro K2000 with driver 470.103.01) I ran into this:
> ...
> FAIL: gcc.dg/atomic/stdatomic-flag-2.c -O1 execution test
> ...
> which mimimized to:
> ...
>   #include <stdatomic.h>
>   atomic_flag a = ATOMIC_FLAG_INIT;
>   int main () {
>     if ((atomic_flag_test_and_set) (&a))
>       __builtin_abort ();
>     return 0;
>   }
> ...
> 
> The atomic_flag_test_and_set is implemented using __atomic_test_and_set_1,
> which corresponds to the "word-sized compare-and-swap loop" version of
> libat_test_and_set in libatomic/tas_n.c.
> 
> The semantics of a test-and-set is that the return value is "true if and only
> if the previous contents were 'set'".
> 
> But the code uses:
> ...
>   return woldval != 0;
> ...
> which means it doesn't look only at the byte that was either set or not set,
> but at the entire word.
> 
> Fix this by using instead:
> ...
>   return (woldval & wval) == wval;

Shouldn't that be instead
  return (woldval & ((UWORD) -1 << shift)) != 0;
or
  return (woldval & ((UWORD) ~(UWORD) 0 << shift)) != 0;
?
The exact __GCC_ATOMIC_TEST_AND_SET_TRUEVAL varies (the most usual
value is 1, but sparc uses 0xff and m68k/sh use 0x80), falseval is
always 0 though and (woldval & wval) == wval
is testing whether some bits of the oldval are all set rather than
whether the old byte was 0.
Say for trueval 1 it tests whether the least significant bit is set,
for 0x80 if the most significant bit of the byte is set, for
0xff whether all bits are set.

        Jakub

Reply via email to