diff options
author | Mikael Ronstrom <mikael@mysql.com> | 2009-12-15 22:15:48 +0100 |
---|---|---|
committer | Mikael Ronstrom <mikael@mysql.com> | 2009-12-15 22:15:48 +0100 |
commit | 0fb1c286d762d94564edaa924de9769c599bc231 (patch) | |
tree | 22be24d6b9d7779f80a3f26169b64f296885c102 /include/atomic | |
parent | 6b0bb0506880d04d6a1d6cd5c6c03f2aebe4ca24 (diff) | |
download | mariadb-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.h | 65 |
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 */ |