diff options
author | Frederic Recoules <frederic.recoules@orange.fr> | 2020-03-05 17:54:48 +0100 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2020-03-12 10:15:56 +0300 |
commit | 31f303835628a9a9f997eaef57ef0ed5b130e2f8 (patch) | |
tree | 37d1a3afab5af6a6a536162b9b5a478dabf3eb4a /src | |
parent | 197aedec657b799b0d19ceb3187893357ccd86fc (diff) | |
download | libatomic_ops-31f303835628a9a9f997eaef57ef0ed5b130e2f8.tar.gz |
Fix gcc/sunc x86 AO_compare_double_and_swap_double missing side effect
(a cherry-pick of commit 43addfe from 'release-7_4')
Bind E/RDX to a dummy output since cmpxchg8/16b clobbers it.
* src/atomic_ops/sysdeps/gcc/x86.h [!__x86_64__]
(AO_compare_double_and_swap_double_full): New local variable (dummy);
specify "=d"(dummy) for asm code.
* src/atomic_ops/sysdeps/gcc/x86_64.h [AO_CMPXCHG16B_AVAILABLE]
(AO_compare_double_and_swap_double_full): Likewise.
* src/atomic_ops/sysdeps/sunc/x86_64.h [AO_CMPXCHG16B_AVAILABLE]
(AO_compare_double_and_swap_double_full): Likewise.
* src/atomic_ops/sysdeps/sunc/x86.h
(AO_compare_double_and_swap_double_full): Remove commented out
function.
Diffstat (limited to 'src')
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/x86.h | 12 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/x86_64.h | 4 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/sunc/x86.h | 37 | ||||
-rw-r--r-- | src/atomic_ops/sysdeps/sunc/x86_64.h | 4 |
4 files changed, 13 insertions, 44 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index 3348845..dfc4a26 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -138,6 +138,7 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) { + AO_t dummy; /* an output for clobbered edx */ char result; # ifdef __PIC__ AO_t saved_ebx; @@ -153,11 +154,12 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, # ifdef __OPTIMIZE__ __asm__ __volatile__("mov %%ebx, %2\n\t" /* save ebx */ "lea %0, %%edi\n\t" /* in case addr is in ebx */ - "mov %7, %%ebx\n\t" /* load new_val1 */ + "mov %8, %%ebx\n\t" /* load new_val1 */ "lock; cmpxchg8b (%%edi)\n\t" "mov %2, %%ebx\n\t" /* restore ebx */ "setz %1" - : "=m" (*addr), "=a" (result), "=m" (saved_ebx) + : "=m" (*addr), "=a" (result), + "=m" (saved_ebx), "=d" (dummy) : "m" (*addr), "d" (old_val2), "a" (old_val1), "c" (new_val2), "m" (new_val1) : "%edi", "memory"); @@ -169,13 +171,13 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, __asm__ __volatile__("mov %%edi, %3\n\t" /* save edi */ "mov %%ebx, %2\n\t" /* save ebx */ "lea %0, %%edi\n\t" /* in case addr is in ebx */ - "mov %8, %%ebx\n\t" /* load new_val1 */ + "mov %9, %%ebx\n\t" /* load new_val1 */ "lock; cmpxchg8b (%%edi)\n\t" "mov %2, %%ebx\n\t" /* restore ebx */ "mov %3, %%edi\n\t" /* restore edi */ "setz %1" : "=m" (*addr), "=a" (result), - "=m" (saved_ebx), "=m" (saved_edi) + "=m" (saved_ebx), "=m" (saved_edi), "=d" (dummy) : "m" (*addr), "d" (old_val2), "a" (old_val1), "c" (new_val2), "m" (new_val1) : "memory"); # endif @@ -184,7 +186,7 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, /* faster) by using ebx as new_val1 (GCC would refuse to compile */ /* such code for PIC mode). */ __asm__ __volatile__("lock; cmpxchg8b %0; setz %1" - : "=m" (*addr), "=a" (result) + : "=m" (*addr), "=a" (result), "=d" (dummy) : "m" (*addr), "d" (old_val2), "a" (old_val1), "c" (new_val2), "b" (new_val1) : "memory"); # endif diff --git a/src/atomic_ops/sysdeps/gcc/x86_64.h b/src/atomic_ops/sysdeps/gcc/x86_64.h index b2e920a..0eb8db4 100644 --- a/src/atomic_ops/sysdeps/gcc/x86_64.h +++ b/src/atomic_ops/sysdeps/gcc/x86_64.h @@ -142,9 +142,11 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) { + AO_t dummy; /* an output for clobbered rdx */ char result; + __asm__ __volatile__("lock; cmpxchg16b %0; setz %1" - : "=m"(*addr), "=a"(result) + : "=m" (*addr), "=a" (result), "=d" (dummy) : "m"(*addr), "d" (old_val2), "a" (old_val1), "c" (new_val2), "b" (new_val1) : "memory"); return (int) result; diff --git a/src/atomic_ops/sysdeps/sunc/x86.h b/src/atomic_ops/sysdeps/sunc/x86.h index fd8e132..4158c02 100644 --- a/src/atomic_ops/sysdeps/sunc/x86.h +++ b/src/atomic_ops/sysdeps/sunc/x86.h @@ -124,41 +124,4 @@ AO_compare_and_swap_full (volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full -#if 0 -/* FIXME: not tested (and probably wrong). Besides, */ -/* it tickles a bug in Sun C 5.10 (when optimizing). */ -/* Returns nonzero if the comparison succeeded. */ -/* Really requires at least a Pentium. */ -AO_INLINE int -AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, - AO_t old_val1, AO_t old_val2, - AO_t new_val1, AO_t new_val2) -{ - char result; -#if __PIC__ - /* If PIC is turned on, we can't use %ebx as it is reserved for the - GOT pointer. We can save and restore %ebx because GCC won't be - using it for anything else (such as any of the m operands) */ - __asm__ __volatile__("pushl %%ebx;" /* save ebx used for PIC GOT ptr */ - "movl %6,%%ebx;" /* move new_val1 to %ebx */ - "lock; cmpxchg8b %0; setz %1;" - "pop %%ebx;" /* restore %ebx */ - : "=m"(*addr), "=a"(result) - : "m"(*addr), "d" (old_val2), "a" (old_val1), - "c" (new_val2), "m" (new_val1) : "memory"); -#else - /* We can't just do the same thing in non-PIC mode, because GCC - * might be using %ebx as the memory operand. We could have ifdef'd - * in a clobber, but there's no point doing the push/pop if we don't - * have to. */ - __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;" - : "=m"(*addr), "=a"(result) - : /* "m"(*addr), */ "d" (old_val2), "a" (old_val1), - "c" (new_val2), "b" (new_val1) : "memory"); -#endif - return (int) result; -} -#define AO_HAVE_compare_double_and_swap_double_full -#endif - #include "../ao_t_is_int.h" diff --git a/src/atomic_ops/sysdeps/sunc/x86_64.h b/src/atomic_ops/sysdeps/sunc/x86_64.h index 2350410..d92da1c 100644 --- a/src/atomic_ops/sysdeps/sunc/x86_64.h +++ b/src/atomic_ops/sysdeps/sunc/x86_64.h @@ -139,9 +139,11 @@ AO_compare_double_and_swap_double_full (volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) { + AO_t dummy; char result; + __asm__ __volatile__ ("lock; cmpxchg16b %0; setz %1" - : "+m" (*addr), "=a" (result) + : "+m" (*addr), "=a" (result), "=d" (dummy) : "d" (old_val2), "a" (old_val1), "c" (new_val2), "b" (new_val1) : "memory"); return (int) result; |