summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-07-29 18:10:05 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-07-29 18:10:05 +0300
commit4b490b83f04560ac4b164ebf93c3583ca8248a7e (patch)
tree0cfe8f4b949cdd5721f471a57a9bb96f293393e7
parent69e188067616d258cdafa5a8a4ac6f03945090a8 (diff)
downloadlibatomic_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.
-rw-r--r--src/atomic_ops/sysdeps/gcc/generic.h12
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 */