Commit be348787 authored by Davi Arnaut's avatar Davi Arnaut

Bug#52419: x86 assembly based atomic CAS causes test failures

The problem was that the x86 assembly based atomic CAS
(compare and swap) implementation could copy the wrong
value to the ebx register, where the cmpxchg8b expects
to see part of the "comparand" value. Since the original
value in the ebx register is saved in the stack (that is,
the push instruction causes the stack pointer to change),
a wrong offset could be used if the compiler decides to
put the source of the comparand value in the stack.

The solution is to copy the comparand value directly from
memory. Since the comparand value is 64-bits wide, it is
copied in two steps over to the ebx and ecx registers.
parent 91392cd8
...@@ -111,9 +111,9 @@ ...@@ -111,9 +111,9 @@
On some platforms (e.g. Mac OS X and Solaris) the ebx register On some platforms (e.g. Mac OS X and Solaris) the ebx register
is held as a pointer to the global offset table. Thus we're not is held as a pointer to the global offset table. Thus we're not
allowed to use the b-register on those platforms when compiling allowed to use the b-register on those platforms when compiling
PIC code, to avoid this we push ebx and pop ebx and add a movl PIC code, to avoid this we push ebx and pop ebx. The new value
instruction to avoid having ebx in the interface of the assembler is copied directly from memory to avoid problems with a implicit
instruction. manipulation of the stack pointer by the push.
cmpxchg8b works on both 32-bit platforms and 64-bit platforms but cmpxchg8b works on both 32-bit platforms and 64-bit platforms but
the code here is only used on 32-bit platforms, on 64-bit the code here is only used on 32-bit platforms, on 64-bit
...@@ -121,11 +121,13 @@ ...@@ -121,11 +121,13 @@
fine. fine.
*/ */
#define make_atomic_cas_body64 \ #define make_atomic_cas_body64 \
int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \ asm volatile ("push %%ebx;" \
asm volatile ("push %%ebx; movl %3, %%ebx;" \ "movl (%%ecx), %%ebx;" \
LOCK_prefix "; cmpxchg8b %0; setz %2; pop %%ebx" \ "movl 4(%%ecx), %%ecx;" \
: "=m" (*a), "+A" (*cmp), "=c" (ret) \ LOCK_prefix "; cmpxchg8b %0;" \
: "m" (ebx), "c" (ecx), "m" (*a) \ "setz %2; pop %%ebx" \
: "=m" (*a), "+A" (*cmp), "=c" (ret) \
: "c" (&set), "m" (*a) \
: "memory", "esp") : "memory", "esp")
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment