Ruby 4.1.0dev (2026-10-06 revision 28da13e768d5a463bec19a874d54d351f41f306f)
ruby_atomic.h (28da13e768d5a463bec19a874d54d351f41f306f)
1#ifndef INTERNAL_ATOMIC_H
2#define INTERNAL_ATOMIC_H
3
4#include "ruby/atomic.h"
5#ifdef HAVE_STDATOMIC_H
6# include <stdatomic.h>
7#endif
8
9#define RUBY_ATOMIC_VALUE_LOAD(x) rbimpl_atomic_value_load(&(x), RBIMPL_ATOMIC_SEQ_CST)
10
11/* shim macros only */
12#define ATOMIC_ADD(var, val) RUBY_ATOMIC_ADD(var, val)
13#define ATOMIC_CAS(var, oldval, newval) RUBY_ATOMIC_CAS(var, oldval, newval)
14#define ATOMIC_DEC(var) RUBY_ATOMIC_DEC(var)
15#define ATOMIC_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
16#define ATOMIC_FETCH_ADD(var, val) RUBY_ATOMIC_FETCH_ADD(var, val)
17#define ATOMIC_FETCH_SUB(var, val) RUBY_ATOMIC_FETCH_SUB(var, val)
18#define ATOMIC_INC(var) RUBY_ATOMIC_INC(var)
19#define ATOMIC_OR(var, val) RUBY_ATOMIC_OR(var, val)
20#define ATOMIC_PTR_CAS(var, oldval, newval) RUBY_ATOMIC_PTR_CAS(var, oldval, newval)
21#define ATOMIC_PTR_EXCHANGE(var, val) RUBY_ATOMIC_PTR_EXCHANGE(var, val)
22#define ATOMIC_SET(var, val) RUBY_ATOMIC_SET(var, val)
23#define ATOMIC_SIZE_ADD(var, val) RUBY_ATOMIC_SIZE_ADD(var, val)
24#define ATOMIC_SIZE_CAS(var, oldval, newval) RUBY_ATOMIC_SIZE_CAS(var, oldval, newval)
25#define ATOMIC_SIZE_DEC(var) RUBY_ATOMIC_SIZE_DEC(var)
26#define ATOMIC_SIZE_EXCHANGE(var, val) RUBY_ATOMIC_SIZE_EXCHANGE(var, val)
27#define ATOMIC_SIZE_INC(var) RUBY_ATOMIC_SIZE_INC(var)
28#define ATOMIC_SIZE_SUB(var, val) RUBY_ATOMIC_SIZE_SUB(var, val)
29#define ATOMIC_SUB(var, val) RUBY_ATOMIC_SUB(var, val)
30#define ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_VALUE_CAS(var, oldval, val)
31#define ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_VALUE_EXCHANGE(var, val)
32
33#define ATOMIC_LOAD_RELAXED(var) rbimpl_atomic_load(&(var), RBIMPL_ATOMIC_RELAXED)
34
35typedef RBIMPL_ALIGNAS(8) uint64_t rbimpl_atomic_uint64_t;
36
37static inline uint64_t
38rbimpl_atomic_u64_load_relaxed(const volatile rbimpl_atomic_uint64_t *value)
39{
40#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
41 return __atomic_load_n(value, __ATOMIC_RELAXED);
42#elif defined(_M_X64) && !defined(_M_ARM64EC)
43 return *value;
44#elif defined(_WIN32)
45 uint64_t val = *value;
46 return InterlockedCompareExchange64(RBIMPL_CAST((uint64_t *)value), val, val);
47#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
48 uint64_t val = *value;
49 return atomic_cas_64(value, val, val);
50#else
51 // TODO: stdatomic
52
53 return *value;
54#endif
55}
56#define ATOMIC_U64_LOAD_RELAXED(var) rbimpl_atomic_u64_load_relaxed(&(var))
57
58static inline void
59rbimpl_atomic_u64_set_relaxed(volatile rbimpl_atomic_uint64_t *address, uint64_t value)
60{
61#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
62 __atomic_store_n(address, value, __ATOMIC_RELAXED);
63#elif defined(_WIN32)
64 InterlockedExchange64(address, value);
65#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
66 atomic_swap_64(address, value);
67#else
68 // TODO: stdatomic
69
70 *address = value;
71#endif
72}
73#define ATOMIC_U64_SET_RELAXED(var, val) rbimpl_atomic_u64_set_relaxed(&(var), val)
74
75static inline uint64_t
76rbimpl_atomic_u64_fetch_add_relaxed(volatile rbimpl_atomic_uint64_t *value, uint64_t addend)
77{
78#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
79 return __atomic_fetch_add(value, addend, __ATOMIC_RELAXED);
80#elif defined(_WIN32)
81 return (uint64_t)InterlockedExchangeAdd64((LONG64 *)value, (LONG64)addend);
82#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
83 return atomic_add_64_nv(value, addend) - addend;
84#else
85 // TODO: stdatomic
86 uint64_t prev = *value;
87 *value = prev + addend;
88 return prev;
89#endif
90}
91#define ATOMIC_U64_FETCH_ADD_RELAXED(var, val) rbimpl_atomic_u64_fetch_add_relaxed(&(var), val)
92
93static inline uint64_t
94rbimpl_atomic_u64_load_acquire(const volatile rbimpl_atomic_uint64_t *value)
95{
96#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
97 return __atomic_load_n(value, __ATOMIC_ACQUIRE);
98#else
99 return rbimpl_atomic_u64_load_relaxed(value);
100#endif
101}
102#define ATOMIC_U64_LOAD_ACQUIRE(var) rbimpl_atomic_u64_load_acquire(&(var))
103
104static inline void
105rbimpl_atomic_u64_set_release(volatile rbimpl_atomic_uint64_t *address, uint64_t value)
106{
107#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
108 __atomic_store_n(address, value, __ATOMIC_RELEASE);
109#else
110 rbimpl_atomic_u64_set_relaxed(address, value);
111#endif
112}
113#define ATOMIC_U64_SET_RELEASE(var, val) rbimpl_atomic_u64_set_release(&(var), val)
114
115#endif
Atomic operations.
#define RBIMPL_ALIGNAS
Wraps (or simulates) alignas.
Definition stdalign.h:57