From 789524842ff50c56daad9c36a783bfa0c6bc76d5 Mon Sep 17 00:00:00 2001 From: Ian Ker-Seymer Date: Thu, 3 May 2018 00:52:17 -0400 Subject: [PATCH] Prefer platform specific memory barriers Following the wisdom of postgres, we opt to use platform specific memory barriers when available. These are generally more performant. In this PR, we add specific cases for i386, x86_64. In the future, we could look at using pg's atomics library directly: https://github.com/postgres/postgres/tree/9d4649ca49416111aee2c84b7e4441a0b7aa2fac/src/include/port/atomics --- ext/concurrent/atomic_reference.c | 36 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/ext/concurrent/atomic_reference.c b/ext/concurrent/atomic_reference.c index e8696086a..6bcbcbc42 100644 --- a/ext/concurrent/atomic_reference.c +++ b/ext/concurrent/atomic_reference.c @@ -9,6 +9,26 @@ #include "atomic_reference.h" +#if (defined(__i386__) || defined(__i386)) && (defined(__GNUC__) || defined(__INTEL_COMPILER)) +#define memory_barrier() \ + __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory", "cc") +#elif defined(__x86_64__) && (defined(__GNUC__) || defined(__INTEL_COMPILER)) +#define memory_barrier() \ + __asm__ __volatile__ ("lock; addl $0,0(%%rsp)" : : : "memory", "cc") +#elif defined(HAVE_GCC__ATOMIC_INT32_CAS) +#define memory_barrier() \ + __atomic_thread_fence(__ATOMIC_SEQ_CST) +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define memory_barrier() \ + __sync_synchronize(); +#elif defined _MSC_VER +#define memory_barrier() \ + MemoryBarrier(); +#elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 +#define memory_barrier() \ + OSMemoryBarrier(); +#endif + void ir_mark(void *value) { rb_gc_mark_maybe((VALUE) value); } @@ -27,25 +47,13 @@ VALUE ir_initialize(int argc, VALUE* argv, VALUE self) { } VALUE ir_get(VALUE self) { -#if HAVE_GCC_SYNC - __sync_synchronize(); -#elif defined _MSC_VER - MemoryBarrier(); -#elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 - OSMemoryBarrier(); -#endif + memory_barrier(); return (VALUE) DATA_PTR(self); } VALUE ir_set(VALUE self, VALUE new_value) { DATA_PTR(self) = (void *) new_value; -#if HAVE_GCC_SYNC - __sync_synchronize(); -#elif defined _MSC_VER - MemoryBarrier(); -#elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 - OSMemoryBarrier(); -#endif + memory_barrier(); return new_value; }