diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2022-07-29 18:10:05 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2022-08-12 00:46:36 +0300 |
commit | e50ada58fc63b620c6270abcc965d802d05057e2 (patch) | |
tree | d6d290a784d01d0dd7d78421c074644cc364031e | |
parent | ed712f7dc6effa68e1d02bc7c21a2dc0504e8cfe (diff) | |
download | libatomic_ops-e50ada58fc63b620c6270abcc965d802d05057e2.tar.gz |
Ensure result of AO_test_and_set is always AO_TS_CLEAR or AO_TS_SET
(fix of commit cbbf8633)
According to the GCC manual, __atomic_test_and_set() result type is
Bool, thus it is not guaranteed to return AO_TS_SET value. (E.g., the
function may return 1 while AO_TS_SET is 255, as observed on sparc64
with gcc-12.)
* src/atomic_ops/sysdeps/gcc/generic.h [!AO_PREFER_GENERALIZED]
(AO_test_and_set, AO_test_and_set_acquire, AO_test_and_set_release,
AO_test_and_set_full): Return AO_TS_SET if __atomic_test_and_set()
result is non-zero, AO_TS_CLEAR otherwise.
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/generic.h | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/generic.h b/src/atomic_ops/sysdeps/gcc/generic.h index 00fd3ac..0a6d032 100644 --- a/src/atomic_ops/sysdeps/gcc/generic.h +++ b/src/atomic_ops/sysdeps/gcc/generic.h @@ -95,28 +95,32 @@ AO_INLINE AO_TS_VAL_t AO_test_and_set(volatile AO_TS_t *addr) { - return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_RELAXED); + return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_RELAXED) + ? AO_TS_SET : AO_TS_CLEAR); } # define AO_HAVE_test_and_set AO_INLINE AO_TS_VAL_t AO_test_and_set_acquire(volatile AO_TS_t *addr) { - return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_ACQUIRE); + return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_ACQUIRE) + ? AO_TS_SET : AO_TS_CLEAR); } # define AO_HAVE_test_and_set_acquire AO_INLINE AO_TS_VAL_t AO_test_and_set_release(volatile AO_TS_t *addr) { - return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_RELEASE); + return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_RELEASE) + ? AO_TS_SET : AO_TS_CLEAR); } # define AO_HAVE_test_and_set_release AO_INLINE AO_TS_VAL_t AO_test_and_set_full(volatile AO_TS_t *addr) { - return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_SEQ_CST); + return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_SEQ_CST) + ? AO_TS_SET : AO_TS_CLEAR); } # define AO_HAVE_test_and_set_full #endif /* !AO_PREFER_GENERALIZED */ |