https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105011

            Bug ID: 105011
           Summary: [nvptx] FAIL: gcc.dg/atomic/stdatomic-flag-2.c   -O1
                    execution test
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vries at gcc dot gnu.org
  Target Milestone: ---

On a quadro k2000 with driver 470.103.01 I'm running into this cluster of
FAILs:
...
FAIL: gcc.dg/atomic/stdatomic-flag-2.c   -O1  execution test
FAIL: gcc.dg/atomic/stdatomic-flag-2.c   -O3 -g  execution test
FAIL: gcc.dg/atomic/stdatomic-flag.c   -O3 -g  execution test
...

Minimizing the first FAIL, I end up with:
...
#include <stdatomic.h>

extern void abort (void);
atomic_flag a = ATOMIC_FLAG_INIT;

int
main ()
{
  int b;

  if ((atomic_flag_test_and_set) (&a))
    abort ();

  return 0;
}
...

The atomic access is done by libatomic, using a 64-bit cas loop.

If we print the address of a, we have:
...
&a: 0000000700700200
...
so the pointer is already 64-bit aligned.

If we print the 64-bit value of *(unsigned long long *)&a before and after the
test-and-set, we have:
...
a: 0000000000024f00
a: 0000000000024f01
...
so that looks all-right as well.

At first glance, the problem is in libatomic, tas_n.c:
...
  wval = (UWORD)__GCC_ATOMIC_TEST_AND_SET_TRUEVAL << shift;
  woldval = __atomic_load_n (wptr, __ATOMIC_RELAXED);
  do
    {
      t = woldval | wval;
    }
  while (!atomic_compare_exchange_w (wptr, &woldval, t, true,
                                     __ATOMIC_RELAXED, __ATOMIC_RELAXED));

  post_barrier (smodel);
  return woldval != 0;
...

What is returned is woldval != 0, but that tests the entire word, not just the
byte we're interested in.

It should probably do something like:
...
  return (woldval & wval) != 0;
...

Reply via email to