diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2022-07-29 18:10:05 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2022-07-29 18:10:05 +0300 |
commit | 4b490b83f04560ac4b164ebf93c3583ca8248a7e (patch) | |
tree | 0cfe8f4b949cdd5721f471a57a9bb96f293393e7 /src | |
parent | 69e188067616d258cdafa5a8a4ac6f03945090a8 (diff) | |
download | libatomic_ops-4b490b83f04560ac4b164ebf93c3583ca8248a7e.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.
Diffstat (limited to 'src')
-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 */ |