diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2022-08-10 11:51:43 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2022-08-24 14:36:25 +0300 |
commit | f3af982b50bbc63e61f0ea55ad8f0768608407d8 (patch) | |
tree | b6f6eabfb5428c937c95a37087815f96b635eab8 | |
parent | 7bd98ae699b3fd3780fad7684f6eda9ff09f9141 (diff) | |
download | libatomic_ops-f3af982b50bbc63e61f0ea55ad8f0768608407d8.tar.gz |
Fix AO_compare_and_swap_full asm code for clang on sparc
(a cherry-pick of commit 124c97a9a from 'master')
Issue #52 (libatomic_ops).
The issue (SIGSEGV in test_malloc) is observed with clang-13, at least.
The workaround is to simplify asm code of AO_compare_and_swap_full
(moving the comparison of CAS result and old value to C code).
* src/atomic_ops/sysdeps/gcc/sparc.h [(!(AO_GNUC_PREREQ(12,0)
|| AO_CLANG_PREREQ(13,0)) || AO_DISABLE_GCC_ATOMICS) && !AO_NO_SPARC_V9
&& !AO_GENERALIZE_ASM_BOOL_CAS] (AO_compare_and_swap_full): Remove ret
local variable; remove cmp, be, mov, clr instructions from asm block
(to match that of AO_fetch_compare_and_swap_full); remove cc from asm
block clobbers; change specifier for old input operand of asm block
(from "0" to "r"); return new_val==old instead of ret.
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/sparc.h | 18 |
1 files changed, 6 insertions, 12 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/sparc.h b/src/atomic_ops/sysdeps/gcc/sparc.h index 2dd2881..434cf58 100644 --- a/src/atomic_ops/sysdeps/gcc/sparc.h +++ b/src/atomic_ops/sysdeps/gcc/sparc.h @@ -43,23 +43,17 @@ AO_test_and_set_full(volatile AO_TS_t *addr) { /* Returns nonzero if the comparison succeeded. */ AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { - AO_t ret; __asm__ __volatile__ ("membar #StoreLoad | #LoadLoad\n\t" # if defined(__arch64__) - "casx [%2],%0,%1\n\t" + "casx [%1],%2,%0\n\t" # else - "cas [%2],%0,%1\n\t" /* 32-bit version */ + "cas [%1],%2,%0\n\t" /* 32-bit version */ # endif "membar #StoreLoad | #StoreStore\n\t" - "cmp %0,%1\n\t" - "be,a 0f\n\t" - "mov 1,%0\n\t"/* one insn after branch always executed */ - "clr %0\n\t" - "0:\n\t" - : "=r" (ret), "+r" (new_val) - : "r" (addr), "0" (old) - : "memory", "cc"); - return (int)ret; + : "+r" (new_val) + : "r" (addr), "r" (old) + : "memory"); + return new_val == old; } # define AO_HAVE_compare_and_swap_full # endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ |