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

boger at gcc dot gnu.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P2
           Severity|normal                      |major

--- Comment #1 from boger at gcc dot gnu.org ---
I have raised this priority because this looks like a bug in the Go code due to
the use of __atomic_compare_exchange_n builtin and how it is implementing the
CompareAndSwapUintptr.

In atomic.c:

_Bool
CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
{
  return __atomic_compare_exchange_n (val, &old, new, true, __ATOMIC_SEQ_CST,

                                      __ATOMIC_RELAXED);
}

The true argument is indicating 'weak' which results in the following code.
Note that there is no guarantee in this code that the CompareAndSwap will do
the store and return true, if it can't get the reservation it will return false
and the store won't happen.

00000000010cc280 <sync..z2fatomic.CompareAndSwapUintptr>:
 10cc280:       ac 04 00 7c     hwsync
 10cc284:       a8 18 20 7d     ldarx   r9,0,r3
 10cc288:       00 20 29 7c     cmpd    r9,r4
 10cc28c:       0c 00 82 40     bne     10cc298
<sync..z2fatomic.CompareAndSwapUintptr+0x18>
 10cc290:       ad 19 a0 7c     stdcx.  r5,0,r3
 10cc294:       2c 01 00 4c     isync
 10cc298:       26 00 78 7c     mfocrf  r3,128
 10cc29c:       fe 1f 63 54     rlwinm  r3,r3,3,31,31
 10cc2a0:       20 00 80 4e     blr


If I look in sync/cond.go check() function:

func (c *copyChecker) check() {
        if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
                !atomic.CompareAndSwapUintptr((*uintptr)(c), 0,
uintptr(unsafe.Pointer(c))) &&
                uintptr(*c) != uintptr(unsafe.Pointer(c)) {
                panic("sync.Cond is copied")
        }
}

This if check assumes that the CompareAndSwapUinptr will do the store if needed
which is not true with the latest implementation of CompareAndSwapUintptr. It
seems that the CompareAndSwapUinptr should be passing the argument to indicate
'strong' and not 'weak'. I made that change and that fixes this problem. I have
not checked the other CompareAndSwaps.

Reply via email to