diff --git a/compiler.hh b/compiler.hh index 6e0c40b..c3a3341 100644 --- a/compiler.hh +++ b/compiler.hh @@ -16,6 +16,7 @@ #ifndef MASSTREE_COMPILER_HH #define MASSTREE_COMPILER_HH 1 #include +#include #define __STDC_FORMAT_MACROS #include #include @@ -91,24 +92,40 @@ inline void fence() { /** @brief Acquire fence. */ inline void acquire_fence() { +#if defined(__x86__) asm volatile("" : : : "memory"); +#else + __sync_synchronize(); +#endif } /** @brief Release fence. */ inline void release_fence() { +#if defined(__x86__) asm volatile("" : : : "memory"); +#else + __sync_synchronize(); +#endif } /** @brief Compiler fence that relaxes the processor. Use this in spinloops, for example. */ inline void relax_fence() { +#if defined(__x86__) asm volatile("pause" : : : "memory"); // equivalent to "rep; nop" +#else + asm volatile("" : : : "memory"); // equivalent to "rep; nop" +#endif } /** @brief Full memory fence. */ inline void memory_fence() { +#if defined(__x86__) asm volatile("mfence" : : : "memory"); +#else + __sync_synchronize(); +#endif } /** @brief Do-nothing function object. */ @@ -157,10 +174,14 @@ template struct sized_compiler_operations; template struct sized_compiler_operations<1, B> { typedef char type; static inline type xchg(type* object, type new_value) { +#if __x86__ asm volatile("xchgb %0,%1" : "+q" (new_value), "+m" (*object)); B()(); return new_value; +#else + return __sync_lock_test_and_set(object, new_value); +#endif } static inline type val_cmpxchg(type* object, type expected, type desired) { #if __x86__ && (PREFER_X86 || !HAVE___SYNC_VAL_COMPARE_AND_SWAP) @@ -213,10 +234,14 @@ template struct sized_compiler_operations<2, B> { typedef int16_t type; #endif static inline type xchg(type* object, type new_value) { +#if __x86__ asm volatile("xchgw %0,%1" : "+r" (new_value), "+m" (*object)); B()(); return new_value; +#else + return __sync_lock_test_and_set(object, new_value); +#endif } static inline type val_cmpxchg(type* object, type expected, type desired) { #if __x86__ && (PREFER_X86 || !HAVE___SYNC_VAL_COMPARE_AND_SWAP) @@ -269,10 +294,14 @@ template struct sized_compiler_operations<4, B> { typedef int32_t type; #endif static inline type xchg(type* object, type new_value) { +#if __x86__ asm volatile("xchgl %0,%1" : "+r" (new_value), "+m" (*object)); B()(); return new_value; +#else + return __sync_lock_test_and_set(object, new_value); +#endif } static inline type val_cmpxchg(type* object, type expected, type desired) { #if __x86__ && (PREFER_X86 || !HAVE___SYNC_VAL_COMPARE_AND_SWAP) @@ -326,14 +355,16 @@ template struct sized_compiler_operations<8, B> { #else typedef int64_t type; #endif -#if __x86_64__ static inline type xchg(type* object, type new_value) { +#if __x86_64__ asm volatile("xchgq %0,%1" : "+r" (new_value), "+m" (*object)); B()(); return new_value; - } +#else + return __sync_lock_test_and_set(object, new_value); #endif + } static inline type val_cmpxchg(type* object, type expected, type desired) { #if __x86_64__ && (PREFER_X86 || !HAVE___SYNC_VAL_COMPARE_AND_SWAP_8) asm volatile("lock; cmpxchgq %2,%1" @@ -568,8 +599,12 @@ inline void prefetch(const void *ptr) { #ifdef NOPREFETCH (void) ptr; #else +#if defined(__x86__) typedef struct { char x[CACHE_LINE_SIZE]; } cacheline_t; asm volatile("prefetcht0 %0" : : "m" (*(const cacheline_t *)ptr)); +#else + __builtin_prefetch(ptr); +#endif #endif } #endif @@ -578,8 +613,12 @@ inline void prefetchnta(const void *ptr) { #ifdef NOPREFETCH (void) ptr; #else +#if defined(__x86__) typedef struct { char x[CACHE_LINE_SIZE]; } cacheline_t; asm volatile("prefetchnta %0" : : "m" (*(const cacheline_t *)ptr)); +#else + __builtin_prefetch(ptr,0,0); +#endif #endif } @@ -612,9 +651,11 @@ inline uint64_t ntohq(uint64_t val) { asm("bswapl %0; bswapl %1; xchgl %0,%1" : "+r" (v.s.a), "+r" (v.s.b)); return v.u; -#else /* __i386__ */ +#elif x86_64 asm("bswapq %0" : "+r" (val)); return val; +#else + return __builtin_bswap64(val); #endif } diff --git a/configure.ac b/configure.ac index b907421..604306c 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,9 @@ KVDB_CHECK_BUILTIN([__builtin_ctzl], KVDB_CHECK_BUILTIN([__builtin_ctzll], [[unsigned long long f(unsigned long long x) { return __builtin_ctzll(x); }]]) +KVDB_CHECK_BUILTIN([__builtin_bswap64], + [[unsigned long long f(unsigned long long x) { return __builtin_bswap64(x); }]]) + KVDB_CHECK_BUILTIN([__sync_synchronize], [[long x = 11; void f(long i) { long* y = &x; __sync_synchronize(); *y = i; }]]) diff --git a/masstree_insert.hh b/masstree_insert.hh index 670f12d..e064386 100644 --- a/masstree_insert.hh +++ b/masstree_insert.hh @@ -131,7 +131,7 @@ void tcursor

::finish_insert() permuter_type perm(n_->permutation_); masstree_invariant(perm.back() == kx_.p); perm.insert_from_back(kx_.i); - fence(); + release_fence(); n_->permutation_ = perm.value(); }