# At a local mysql-5.5-bugfixing repository of davi
3207 Davi Arnaut 2010-09-17
Bug#52419: Test "binlog_stm_mix_innodb_myisam" fails, complains about non-transactional
The problem was that the x86 ASM atomic compare and swap
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.
modified:
include/atomic/x86-gcc.h
=== modified file 'include/atomic/x86-gcc.h'
--- a/include/atomic/x86-gcc.h 2010-07-23 12:37:10 +0000
+++ b/include/atomic/x86-gcc.h 2010-09-17 16:54:44 +0000
@@ -121,11 +121,13 @@
fine.
*/
#define make_atomic_cas_body64 \
- int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \
- asm volatile ("push %%ebx; movl %3, %%ebx;" \
- LOCK_prefix "; cmpxchg8b %0; setz %2; pop %%ebx" \
- : "=m" (*a), "+A" (*cmp), "=c" (ret) \
- : "m" (ebx), "c" (ecx), "m" (*a) \
+ asm volatile ("push %%ebx;" \
+ "movl (%%ecx), %%ebx;" \
+ "movl 4(%%ecx), %%ecx;" \
+ LOCK_prefix "; cmpxchg8b %0;" \
+ "setz %2; pop %%ebx" \
+ : "=m" (*a), "+A" (*cmp), "=c" (ret) \
+ : "c" (&set), "m" (*a) \
: "memory", "esp")
#endif
Attachment: [text/bzr-bundle] bzr/davi.arnaut@oracle.com-20100917165444-o181h42wdza6lupo.bundle
| Thread |
|---|
| • bzr commit into mysql-5.5-bugfixing branch (davi:3207) Bug#52419 | Davi Arnaut | 17 Sep |