Hi Folks, This is a work in progress. It builds on v7, but I've not tested yet. We've a few dependency issues building this on F19 just now, but it will build for v7 against 2.2.3 on F18 as well locally. If someone with more knowledge of mongo would like to take a poke/test, cool. I have done a literal port of the x86_64 implementation (hence it contains a few superfluous bits intentionally). It'll need cleaning up. Jon.
diff -urNp mongodb-src-r2.2.3_orig/src/mongo/bson/util/atomic_int.h mongodb-src-r2.2.3/src/mongo/bson/util/atomic_int.h --- mongodb-src-r2.2.3_orig/src/mongo/bson/util/atomic_int.h 2013-01-31 10:18:33.000000000 -0500 +++ mongodb-src-r2.2.3/src/mongo/bson/util/atomic_int.h 2013-02-19 00:12:16.580841779 -0500 @@ -90,7 +90,9 @@ namespace mongo { void AtomicUInt::signedAdd(int by) { __sync_fetch_and_add(&x, by); } -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__) || defined(__arm__)) + +#if defined(__i386__) || defined(__x86_64__) inline void AtomicUInt::set(unsigned newX) { asm volatile("mfence" ::: "memory"); x = newX; @@ -109,6 +111,31 @@ namespace mongo { ); return r; } +#endif + +#if defined(__arm__) + inline void AtomicUInt::set(unsigned newX) { + asm volatile("mcr p15, 0, r0, c7, c10, 5"); + x = newX; + } + + typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr); + #define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0) + + inline unsigned atomic_int_helper(volatile unsigned *x, int val) { + { + int old, new; + + do { + old = *ptr; + new = old + val; + } while(__kuser_cmpxchg(old, new, ptr)); + + return old; + } + +#endif + AtomicUInt AtomicUInt::operator++() { return atomic_int_helper(&x, 1)+1; } diff -urNp mongodb-src-r2.2.3_orig/src/mongo/platform/atomic_intrinsics_gcc.h mongodb-src-r2.2.3/src/mongo/platform/atomic_intrinsics_gcc.h --- mongodb-src-r2.2.3_orig/src/mongo/platform/atomic_intrinsics_gcc.h 2013-01-31 10:18:33.000000000 -0500 +++ mongodb-src-r2.2.3/src/mongo/platform/atomic_intrinsics_gcc.h 2013-02-19 11:21:29.988914574 -0500 @@ -14,14 +14,23 @@ */ /** - * Implementation of the AtomicIntrinsics<T>::* operations for IA-32 and AMD64 systems using a - * GCC-compatible compiler toolchain. + * Implementation of the AtomicIntrinsics<T>::* operations for IA-32, AMD64, and 32-bit ARM + * systems using a GCC-compatible compiler toolchain. */ #pragma once #include <boost/utility.hpp> +#if defined(__arm__) +typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr); +#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0) +typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval, + const int64_t *newval, + volatile int64_t *ptr); +#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60) +#endif + namespace mongo { /** @@ -37,48 +46,106 @@ namespace mongo { static T compareAndSwap(volatile T* dest, T expected, T newValue) { T result; + +#if defined(__i386__) || defined(__x86_64__) asm volatile ("lock cmpxchg %[src], %[dest]" : [dest] "+m" (*dest), "=a" (result) : [src] "r" (newValue), "a" (expected) : "memory", "cc"); +#endif + +#if defined(__arm__) + if (__kuser_cmpxchg((int)expected, (int)newValue, + (volatile int *)dest) == 0) + result = newValue; + else + result = *dest; +#endif + return result; } static T swap(volatile T* dest, T newValue) { T result = newValue; + +#if defined(__i386__) || defined(__x86_64__) // No need for "lock" prefix on "xchg". asm volatile ("xchg %[r], %[dest]" : [dest] "+m" (*dest), [r] "+r" (result) : : "memory"); +#endif + +#if defined(__arm__) + do { + // nothing + } while (__kuser_cmpxchg((int)(*dest), (int)newValue, + (volatile int *)dest)); +#endif + return result; } static T load(volatile const T* value) { + +#if defined(__i386__) || defined(__x86_64__) asm volatile ("mfence" ::: "memory"); T result = *value; asm volatile ("mfence" ::: "memory"); +#endif + +#if defined(__arm__) + asm volatile("mcr p15, 0, r0, c7, c10, 5"); + T result = *value; + asm volatile("mcr p15, 0, r0, c7, c10, 5"); +#endif + return result; } static void store(volatile T* dest, T newValue) { + +#if defined(__i386__) || defined(__x86_64__) asm volatile ("mfence" ::: "memory"); *dest = newValue; asm volatile ("mfence" ::: "memory"); +#endif + +#if defined(__arm__) + asm volatile("mcr p15, 0, r0, c7, c10, 5"); + *dest = newValue; + asm volatile("mcr p15, 0, r0, c7, c10, 5"); +#endif + } static T fetchAndAdd(volatile T* dest, T increment) { T result = increment; + +#if defined(__i386__) || defined(__x86_64__) asm volatile ("lock xadd %[src], %[dest]" : [dest] "+m" (*dest), [src] "+r" (result) : : "memory", "cc"); +#endif + +#if defined(__arm__) + int old; + + do { + old = (int)(*dest); + } while(__kuser_cmpxchg((int)old, (int)(old+increment), + (volatile int *)dest)); + + result = old; +#endif + return result; } @@ -101,6 +168,8 @@ namespace mongo { public: static T compareAndSwap(volatile T* dest, T expected, T newValue) { T result = expected; + +#if defined(__i386__) || defined(__x86_64__) asm volatile ("push %%eax\n" "push %%ebx\n" "push %%ecx\n" @@ -121,6 +190,16 @@ namespace mongo { "D" (&result), "d" (&newValue) : "memory", "cc"); +#endif + +#if defined(__arm__) + if (__kuser_cmpxchg64((const int64_t *)&expected, (const int64_t *)&newValue, + (volatile int64_t *)dest) == 0) + result = newValue; + else + result = *dest; +#endif + return result; } diff -urNp mongodb-src-r2.2.3_orig/src/mongo/platform/bits.h mongodb-src-r2.2.3/src/mongo/platform/bits.h --- mongodb-src-r2.2.3_orig/src/mongo/platform/bits.h 2013-01-31 10:18:33.000000000 -0500 +++ mongodb-src-r2.2.3/src/mongo/platform/bits.h 2013-02-19 11:11:14.537944114 -0500 @@ -21,7 +21,7 @@ #if defined(__x86_64__) || defined(__amd64__) || defined(_WIN64) #define MONGO_PLATFORM_64 -#elif defined(__i386__) || defined(_WIN32) +#elif defined(__i386__) || defined(_WIN32) || defined(__arm__) #define MONGO_PLATFORM_32 #else #error "unknown platform"
_______________________________________________ arm mailing list arm@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/arm