platform_atomic.h (9534B)
1 #pragma once 2 3 #include "intrinsics.h" 4 #include "platform.h" 5 6 /* 7 * non-relacy things 8 */ 9 #if !PLATFORM_RELACY 10 11 enum NonAtomicDollar { NONATOMIC_DOLLAR }; 12 #define $ NONATOMIC_DOLLAR 13 14 template< typename T > 15 struct NonAtomic { 16 T x; 17 T & operator()( NonAtomicDollar ) { 18 return x; 19 } 20 }; 21 22 #define NONATOMIC( T ) NonAtomic< T > 23 24 #endif 25 26 /* 27 * GCC/clang 28 */ 29 #if !PLATFORM_RELACY && PLATFORM_GCCORCLANG 30 31 struct atomic_s32 { 32 NONCOPYABLE( atomic_s32 ); 33 atomic_s32() { store_relaxed( this, 0 ); } 34 atomic_s32( s32 x ) { store_relaxed( this, x ); } 35 s32 v; 36 }; 37 38 struct atomic_s64 { 39 NONCOPYABLE( atomic_s64 ); 40 atomic_s64() { store_relaxed( this, 0 ); } 41 atomic_s64( s64 x ) { store_relaxed( this, x ); } 42 s64 v; 43 }; 44 45 struct atomic_u32 { 46 NONCOPYABLE( atomic_u32 ); 47 atomic_u32() { store_relaxed( this, 0 ); } 48 atomic_u32( u32 x ) { store_relaxed( this, x ); } 49 u32 v; 50 }; 51 52 struct atomic_u64 { 53 NONCOPYABLE( atomic_u64 ); 54 atomic_u64() { store_relaxed( this, 0 ); } 55 atomic_u64( u64 x ) { store_relaxed( this, x ); } 56 u64 v; 57 }; 58 59 #define load_relaxed( atom ) __atomic_load_n( &( atom )->v, __ATOMIC_RELAXED ) 60 #define store_relaxed( atom, x ) __atomic_store_n( &( atom )->v, ( x ), __ATOMIC_RELAXED ) 61 #define fetch_add_relaxed( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_RELAXED ) 62 #define fetch_sub_relaxed( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_RELAXED ) 63 #define exchange_relaxed( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_RELAXED ) 64 #define compare_exchange_relaxed( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) 65 66 #define load_acquire( atom ) __atomic_load_n( &( atom )->v, __ATOMIC_ACQUIRE ) 67 #define fetch_add_acquire( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_ACQUIRE ) 68 #define fetch_sub_acquire( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_ACQUIRE ) 69 #define exchange_acquire( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_ACQUIRE ) 70 #define compare_exchange_acquire( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE ) 71 72 #define store_release( atom, x ) __atomic_store_n( &( atom )->v, ( x ), __ATOMIC_RELEASE ) 73 #define fetch_add_release( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_RELEASE ) 74 #define fetch_sub_release( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_RELEASE ) 75 #define exchange_release( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_RELEASE ) 76 #define compare_exchange_release( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_RELEASE, __ATOMIC_RELAXED ) 77 78 #define fetch_add_acqrel( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_ACQ_REL ) 79 #define fetch_sub_acqrel( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_ACQ_REL ) 80 #define exchange_acqrel( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_ACQ_REL ) 81 #define compare_exchange_acqrel( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE ) 82 83 #define load_seqcst( atom ) __atomic_load_n( &( atom )->v, __ATOMIC_SEQ_CST ) 84 #define store_seqcst( atom, x ) __atomic_store_n( &( atom )->v, ( x ), __ATOMIC_SEQ_CST ) 85 #define fetch_add_seqcst( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_SEQ_CST ) 86 #define fetch_sub_seqcst( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_SEQ_CST ) 87 #define exchange_seqcst( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_SEQ_CST ) 88 #define compare_exchange_seqcst( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) 89 90 #endif 91 92 /* 93 * std::atomic 94 */ 95 #if !PLATFORM_RELACY && !PLATFORM_GCCORCLANG 96 97 #include <atomic> 98 99 typedef std::atomic< s32 > atomic_s32; 100 typedef std::atomic< s64 > atomic_s64; 101 typedef std::atomic< u32 > atomic_u32; 102 typedef std::atomic< u64 > atomic_u64; 103 104 #define load_relaxed( atom ) ( atom )->load( std::memory_order_relaxed ) 105 #define store_relaxed( atom, x ) ( atom )->store( x, std::memory_order_relaxed ) 106 #define fetch_add_relaxed( atom, x ) ( atom )->fetch_add( x, std::memory_order_relaxed ) 107 #define fetch_sub_relaxed( atom, x ) ( atom )->fetch_sub( x, std::memory_order_relaxed ) 108 #define exchange_relaxed( atom, x ) ( atom )->exchange( x, std::memory_order_relaxed ) 109 #define compare_exchange_relaxed( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_relaxed, std::memory_order_relaxed ) 110 111 #define load_acquire( atom ) ( atom )->load( std::memory_order_acquire ) 112 #define fetch_add_acquire( atom, x ) ( atom )->fetch_add( x, std::memory_order_acquire ) 113 #define fetch_sub_acquire( atom, x ) ( atom )->fetch_sub( x, std::memory_order_acquire ) 114 #define exchange_acquire( atom, x ) ( atom )->exchange( x, std::memory_order_acquire ) 115 #define compare_exchange_acquire( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_acquire, std::memory_order_acquire ) 116 117 #define store_release( atom, x ) ( atom )->store( x, std::memory_order_release ) 118 #define fetch_add_release( atom, x ) ( atom )->fetch_add( x, std::memory_order_release ) 119 #define fetch_sub_release( atom, x ) ( atom )->fetch_sub( x, std::memory_order_release ) 120 #define exchange_release( atom, x ) ( atom )->exchange( x, std::memory_order_release ) 121 #define compare_exchange_release( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_release, std::memory_order_relaxed ) 122 123 #define fetch_add_acqrel( atom, x ) ( atom )->fetch_add( x, std::memory_order_acq_rel ) 124 #define fetch_sub_acqrel( atom, x ) ( atom )->fetch_sub( x, std::memory_order_acq_rel ) 125 #define exchange_acqrel( atom, x ) ( atom )->exchange( x, std::memory_order_acq_rel ) 126 #define compare_exchange_acqrel( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_acq_rel, std::memory_order_acquire ) 127 128 #define load_seqcst( atom ) ( atom )->load( std::memory_order_seq_cst ) 129 #define store_seqcst( atom, x ) ( atom )->store( x, std::memory_order_seq_cst ) 130 #define fetch_add_seqcst( atom, x ) ( atom )->fetch_add( x, std::memory_order_seq_cst ) 131 #define fetch_sub_seqcst( atom, x ) ( atom )->fetch_sub( x, std::memory_order_seq_cst ) 132 #define exchange_seqcst( atom, x ) ( atom )->exchange( x, std::memory_order_seq_cst ) 133 #define compare_exchange_seqcst( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_seq_cst, std::memory_order_seq_cst ) 134 135 #endif 136 137 /* 138 * relacy 139 */ 140 #if PLATFORM_RELACY 141 142 #define NONATOMIC( T ) rl::var< T > 143 #define ATOMIC_ASSERT( p ) RL_ASSERT( p ) 144 145 #define atomic_s32 rl::atomic< s32 > 146 #define atomic_s64 rl::atomic< s64 > 147 #define atomic_u32 rl::atomic< u32 > 148 #define atomic_u64 rl::atomic< u64 > 149 150 #define load_relaxed( atom ) ( atom )->load( rl::memory_order_relaxed ) 151 #define store_relaxed( atom, x ) ( atom )->store( x, rl::memory_order_relaxed ) 152 #define fetch_add_relaxed( atom, x ) ( atom )->fetch_add( x, rl::memory_order_relaxed ) 153 #define fetch_sub_relaxed( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_relaxed ) 154 #define exchange_relaxed( atom, x ) ( atom )->exchange( x, rl::memory_order_relaxed ) 155 #define compare_exchange_relaxed( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_relaxed, rl::memory_order_relaxed ) 156 157 #define load_acquire( atom ) ( atom )->load( rl::memory_order_acquire ) 158 #define fetch_add_acquire( atom, x ) ( atom )->fetch_add( x, rl::memory_order_acquire ) 159 #define fetch_sub_acquire( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_acquire ) 160 #define exchange_acquire( atom, x ) ( atom )->exchange( x, rl::memory_order_acquire ) 161 #define compare_exchange_acquire( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_acquire, rl::memory_order_acquire ) 162 163 #define store_release( atom, x ) ( atom )->store( x, rl::memory_order_release ) 164 #define fetch_add_release( atom, x ) ( atom )->fetch_add( x, rl::memory_order_release ) 165 #define fetch_sub_release( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_release ) 166 #define exchange_release( atom, x ) ( atom )->exchange( x, rl::memory_order_release ) 167 #define compare_exchange_release( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_release, rl::memory_order_relaxed ) 168 169 #define fetch_add_acqrel( atom, x ) ( atom )->fetch_add( x, rl::memory_order_acq_rel ) 170 #define fetch_sub_acqrel( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_acq_rel ) 171 #define exchange_acqrel( atom, x ) ( atom )->exchange( x, rl::memory_order_acq_rel ) 172 #define compare_exchange_acqrel( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_acq_rel, rl::memory_order_acquire ) 173 174 #define load_seqcst( atom ) ( atom )->load( rl::memory_order_seq_cst ) 175 #define store_seqcst( atom, x ) ( atom )->store( x, rl::memory_order_seq_cst ) 176 #define fetch_add_seqcst( atom, x ) ( atom )->fetch_add( x, rl::memory_order_seq_cst ) 177 #define fetch_sub_seqcst( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_seq_cst ) 178 #define exchange_seqcst( atom, x ) ( atom )->exchange( x, rl::memory_order_seq_cst ) 179 #define compare_exchange_seqcst( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_seq_cst, rl::memory_order_seq_cst ) 180 181 #endif