summaryrefslogtreecommitdiff
path: root/include/atomic
diff options
context:
space:
mode:
authorMikael Ronstrom <mikael@mysql.com>2009-12-15 22:15:48 +0100
committerMikael Ronstrom <mikael@mysql.com>2009-12-15 22:15:48 +0100
commit0fb1c286d762d94564edaa924de9769c599bc231 (patch)
tree22be24d6b9d7779f80a3f26169b64f296885c102 /include/atomic
parent6b0bb0506880d04d6a1d6cd5c6c03f2aebe4ca24 (diff)
downloadmariadb-git-0fb1c286d762d94564edaa924de9769c599bc231.tar.gz
Fixed complex gcc assembler issues with 64-bit operations on 32-bit platforms using PIC codes, commented x86-gcc.h a lot more
Diffstat (limited to 'include/atomic')
-rw-r--r--include/atomic/x86-gcc.h65
1 files changed, 47 insertions, 18 deletions
diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h
index f19a4a33f3c..32839e0a67d 100644
--- a/include/atomic/x86-gcc.h
+++ b/include/atomic/x86-gcc.h
@@ -59,39 +59,68 @@
asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \
: "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set))
-#define make_atomic_cas_bodyptr make_atomic_cas_body32
-
-#ifndef __x86_64__
+#ifdef __x86_64__
#define make_atomic_add_body64 make_atomic_add_body32
#define make_atomic_cas_body64 make_atomic_cas_body32
+
+#define make_atomic_fas_body(S) \
+ asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a))
+
+/*
+ Actually 32-bit reads/writes are always atomic on x86
+ But we add LOCK_prefix here anyway to force memory barriers
+*/
+#define make_atomic_load_body(S) \
+ ret=0; \
+ asm volatile (LOCK_prefix "; cmpxchg %2, %0" \
+ : "+m" (*a), "+a" (ret): "r" (ret))
+#define make_atomic_store_body(S) \
+ asm volatile ("; xchg %0, %1;" : "+m" (*a), "+r" (v))
+
#else
+/*
+ Use default implementations of 64-bit operations since we solved
+ the 64-bit problem on 32-bit platforms for CAS, no need to solve it
+ once more for ADD, LOAD, STORE and FAS as well.
+ Since we already added add32 support, we need to define add64
+ here, but we haven't defined fas, load and store at all, so
+ we can fallback on default implementations.
+*/
#define make_atomic_add_body64 \
int64 tmp=*a; \
while (!my_atomic_cas64(a, &tmp, tmp+v)); \
v=tmp;
+
+/*
+ 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
+ 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
+ instruction to avoid having ebx in the interface of the assembler
+ instruction.
+
+ 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
+ platforms the much simpler make_atomic_cas_body32 will work
+ fine.
+*/
#define make_atomic_cas_body64 \
int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \
- asm volatile (LOCK_prefix "; cmpxchg8b %0; setz %2;" \
+ asm volatile ("push %%ebx; movl %3, %%ebx;" \
+ LOCK_prefix "; cmpxchg8b %0; setz %2; pop %%ebx"\
: "+m" (*a), "+A" (*cmp), "=q" (ret) \
- :"b" (ebx), "c" (ecx))
+ :"m" (ebx), "c" (ecx))
#endif
-#define make_atomic_fas_body(S) \
- asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a))
+/*
+ The implementation of make_atomic_cas_body32 is adaptable to
+ the OS word size, so on 64-bit platforms it will automatically
+ adapt to 64-bits and so it will work also on 64-bit platforms
+*/
+#define make_atomic_cas_bodyptr make_atomic_cas_body32
#ifdef MY_ATOMIC_MODE_DUMMY
#define make_atomic_load_body(S) ret=*a
#define make_atomic_store_body(S) *a=v
-#else
-/*
- Actually 32-bit reads/writes are always atomic on x86
- But we add LOCK_prefix here anyway to force memory barriers
-*/
-#define make_atomic_load_body(S) \
- ret=0; \
- asm volatile (LOCK_prefix "; cmpxchg %2, %0" \
- : "+m" (*a), "+a" (ret): "r" (ret))
-#define make_atomic_store_body(S) \
- asm volatile ("; xchg %0, %1;" : "+m" (*a), "+r" (v))
#endif
#endif /* ATOMIC_X86_GCC_INCLUDED */