summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrederic Recoules <frederic.recoules@orange.fr>2020-03-05 17:54:48 +0100
committerIvan Maidanski <ivmai@mail.ru>2020-03-12 10:15:56 +0300
commit31f303835628a9a9f997eaef57ef0ed5b130e2f8 (patch)
tree37d1a3afab5af6a6a536162b9b5a478dabf3eb4a /src
parent197aedec657b799b0d19ceb3187893357ccd86fc (diff)
downloadlibatomic_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.h12
-rw-r--r--src/atomic_ops/sysdeps/gcc/x86_64.h4
-rw-r--r--src/atomic_ops/sysdeps/sunc/x86.h37
-rw-r--r--src/atomic_ops/sysdeps/sunc/x86_64.h4
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;