summaryrefslogtreecommitdiff
path: root/ruby_atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_atomic.h')
-rw-r--r--ruby_atomic.h47
1 files changed, 47 insertions, 0 deletions
diff --git a/ruby_atomic.h b/ruby_atomic.h
index ad53356f06..409b9bcfd2 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -2,6 +2,9 @@
#define INTERNAL_ATOMIC_H
#include "ruby/atomic.h"
+#ifdef HAVE_STDATOMIC_H
+# include <stdatomic.h>
+#endif
#define RUBY_ATOMIC_VALUE_LOAD(x) rbimpl_atomic_value_load(&(x), RBIMPL_ATOMIC_SEQ_CST)
@@ -43,6 +46,8 @@ rbimpl_atomic_u64_load_relaxed(const volatile rbimpl_atomic_uint64_t *value)
uint64_t val = *value;
return atomic_cas_64(value, val, val);
#else
+ // TODO: stdatomic
+
return *value;
#endif
}
@@ -58,9 +63,51 @@ rbimpl_atomic_u64_set_relaxed(volatile rbimpl_atomic_uint64_t *address, uint64_t
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
atomic_swap_64(address, value);
#else
+ // TODO: stdatomic
+
*address = value;
#endif
}
#define ATOMIC_U64_SET_RELAXED(var, val) rbimpl_atomic_u64_set_relaxed(&(var), val)
+static inline uint64_t
+rbimpl_atomic_u64_fetch_add_relaxed(volatile rbimpl_atomic_uint64_t *value, uint64_t addend)
+{
+#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
+ return __atomic_fetch_add(value, addend, __ATOMIC_RELAXED);
+#elif defined(_WIN32)
+ return (uint64_t)InterlockedExchangeAdd64((LONG64 *)value, (LONG64)addend);
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ return atomic_add_64_nv(value, addend) - addend;
+#else
+ // TODO: stdatomic
+ uint64_t prev = *value;
+ *value = prev + addend;
+ return prev;
+#endif
+}
+#define ATOMIC_U64_FETCH_ADD_RELAXED(var, val) rbimpl_atomic_u64_fetch_add_relaxed(&(var), val)
+
+static inline uint64_t
+rbimpl_atomic_u64_load_acquire(const volatile rbimpl_atomic_uint64_t *value)
+{
+#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
+ return __atomic_load_n(value, __ATOMIC_ACQUIRE);
+#else
+ return rbimpl_atomic_u64_load_relaxed(value);
+#endif
+}
+#define ATOMIC_U64_LOAD_ACQUIRE(var) rbimpl_atomic_u64_load_acquire(&(var))
+
+static inline void
+rbimpl_atomic_u64_set_release(volatile rbimpl_atomic_uint64_t *address, uint64_t value)
+{
+#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
+ __atomic_store_n(address, value, __ATOMIC_RELEASE);
+#else
+ rbimpl_atomic_u64_set_relaxed(address, value);
+#endif
+}
+#define ATOMIC_U64_SET_RELEASE(var, val) rbimpl_atomic_u64_set_release(&(var), val)
+
#endif