4#define CX_MemoryBarrier __faststorefence
5#define CX_ReadWriteBarrier _ReadWriteBarrier
7__forceinline
void CX_MemoryBarrier(
void)
11 _InterlockedOr(&Barrier, 0);
14#define CX_ReadWriteBarrier _ReadWriteBarrier
16#error "Don't know how to create atomics for this platform for MSVC."
19#include "cx/utils/macros.h"
21#define atomicInit(...) \
34typedef char _cx_atomic_repr_0_t;
35typedef short _cx_atomic_repr_1_t;
36typedef long _cx_atomic_repr_2_t;
37typedef __int64 _cx_atomic_repr_3_t;
42_meta_inline _cx_atomic_repr_0_t _cx_atomic_rawLoad_0(
const _cx_atomic_repr_0_t* p)
46_meta_inline
void _cx_atomic_rawStore_0(_cx_atomic_repr_0_t* p, _cx_atomic_repr_0_t val)
50_meta_inline _cx_atomic_repr_1_t _cx_atomic_rawLoad_1(
const _cx_atomic_repr_1_t* p)
54_meta_inline
void _cx_atomic_rawStore_1(_cx_atomic_repr_1_t* p, _cx_atomic_repr_1_t val)
58_meta_inline _cx_atomic_repr_2_t _cx_atomic_rawLoad_2(
const _cx_atomic_repr_2_t* p)
62_meta_inline
void _cx_atomic_rawStore_2(_cx_atomic_repr_2_t* p, _cx_atomic_repr_2_t val)
72#define CX_ATOMIC_IL_SUFFIX_3 64_cx_x86
80_meta_inline _cx_atomic_repr_3_t _cx_atomic_rawLoad_3(
const _cx_atomic_repr_3_t* p)
82 _cx_atomic_repr_3_t ret;
83 _mm_storel_epi64((__m128i*)&ret, _mm_loadl_epi64((
const __m128i*)p));
86_meta_inline
void _cx_atomic_rawStore_3(_cx_atomic_repr_3_t* p, _cx_atomic_repr_3_t val)
88 _mm_storel_epi64((__m128i*)p, _mm_loadl_epi64((
const __m128i*)&val));
96_meta_inline _cx_atomic_repr_3_t _cx_atomic_rawLoad_3(
const _cx_atomic_repr_3_t* p)
98 _cx_atomic_repr_3_t* pw = (_cx_atomic_repr_3_t*)p;
99 return _InterlockedCompareExchange64(pw, 0, 0);
101_meta_inline
void _cx_atomic_rawStore_3(_cx_atomic_repr_3_t* p, _cx_atomic_repr_3_t val)
103 _cx_atomic_repr_3_t old = *p;
105 _cx_atomic_repr_3_t prev = _InterlockedCompareExchange64(p, val, old);
115_meta_inline _cx_atomic_repr_3_t _InterlockedCompareExchange64_cx_x86(_cx_atomic_repr_3_t* p,
116 _cx_atomic_repr_3_t xchg,
117 _cx_atomic_repr_3_t comp)
119 return _InterlockedCompareExchange64(p, xchg, comp);
125#define _CX_X86_ATOMIC64_RMW(name, expr) \
126 _meta_inline _cx_atomic_repr_3_t name##64_cx_x86(_cx_atomic_repr_3_t * p, \
127 _cx_atomic_repr_3_t val) \
129 _cx_atomic_repr_3_t old = *p; \
131 _cx_atomic_repr_3_t desired = (expr); \
132 _cx_atomic_repr_3_t prev = _InterlockedCompareExchange64(p, desired, old); \
140_CX_X86_ATOMIC64_RMW(_InterlockedExchange, val)
141_CX_X86_ATOMIC64_RMW(_InterlockedExchangeAdd,
142 (_cx_atomic_repr_3_t)((
unsigned __int64)old + (
unsigned __int64)val))
143_CX_X86_ATOMIC64_RMW(_InterlockedAnd, old & val)
144_CX_X86_ATOMIC64_RMW(_InterlockedOr, old | val)
145_CX_X86_ATOMIC64_RMW(_InterlockedXor, old ^ val)
149#define CX_ATOMIC_IL_SUFFIX_3 64
151_meta_inline _cx_atomic_repr_3_t _cx_atomic_rawLoad_3(
const _cx_atomic_repr_3_t* p)
155_meta_inline
void _cx_atomic_rawStore_3(_cx_atomic_repr_3_t* p, _cx_atomic_repr_3_t val)
162_meta_inline
void _atomicFence(AtmoicMemoryOrder mo)
164 CX_ReadWriteBarrier();
165#if defined(_M_ARM) || defined(_M_ARM64)
167 if (mo != ATOMIC_MO_Relaxed) {
170#elif defined(_M_IX86) || defined(_M_X64)
172 if (mo == ATOMIC_MO_SeqCst) {
176#error "Don't know how to create atomics for this platform for MSVC."
178 CX_ReadWriteBarrier();
180#define atomicFence(order) _atomicFence(ATOMIC_MO_##order)
182#define CX_ATOMIC_IL_REPR(lg_size) _cx_atomic_repr_##lg_size##_t
184#define CX_ATOMIC_IL_NAME(base_name, lg_size) tokconcat(base_name, CX_ATOMIC_IL_SUFFIX(lg_size))
186#define CX_ATOMIC_IL_SUFFIX(lg_size) tokconcat(CX_ATOMIC_IL_SUFFIX_, lg_size)
188#define CX_ATOMIC_IL_SUFFIX_0 8
189#define CX_ATOMIC_IL_SUFFIX_1 16
190#define CX_ATOMIC_IL_SUFFIX_2
194#define CX_ATOMIC_IL_RAWLOAD(lg_size) tokconcat(_cx_atomic_rawLoad_, lg_size)
195#define CX_ATOMIC_IL_RAWSTORE(lg_size) tokconcat(_cx_atomic_rawStore_, lg_size)
197#define CX_ATOMIC_IL_ALIGN(lg_size) tokconcat(CX_ATOMIC_IL_ALIGN_, lg_size)
198#define CX_ATOMIC_IL_ALIGN_0
199#define CX_ATOMIC_IL_ALIGN_1
200#define CX_ATOMIC_IL_ALIGN_2
204#define CX_ATOMIC_IL_ALIGN_3 alignMem(8)
206#define CX_ATOMIC_IL_ALIGN_3
209#define atomic(type) cx_atomic_##type
210#define atomicLoad(type, atomic_ptr, order) _atomicLoad_##type(atomic_ptr, ATOMIC_MO_##order)
211#define atomicStore(type, atomic_ptr, val, order) \
212 _atomicStore_##type(atomic_ptr, val, ATOMIC_MO_##order)
213#define atomicExchange(type, atomic_ptr, val, order) \
214 _atomicExchange_##type(atomic_ptr, val, ATOMIC_MO_##order)
215#define atomicCompareExchange(type, \
222 _atomicCompareExchange_##semantics##_##type(atomic_ptr, \
225 ATOMIC_MO_##successorder, \
226 ATOMIC_MO_##failorder)
228#define atomicFetchAdd(type, atomic_ptr, val, order) \
229 _atomicFetchAdd_##type(atomic_ptr, val, ATOMIC_MO_##order)
230#define atomicFetchSub(type, atomic_ptr, val, order) \
231 _atomicFetchSub_##type(atomic_ptr, val, ATOMIC_MO_##order)
232#define atomicFetchAnd(type, atomic_ptr, val, order) \
233 _atomicFetchAnd_##type(atomic_ptr, val, ATOMIC_MO_##order)
234#define atomicFetchOr(type, atomic_ptr, val, order) \
235 _atomicFetchOr_##type(atomic_ptr, val, ATOMIC_MO_##order)
236#define atomicFetchXor(type, atomic_ptr, val, order) \
237 _atomicFetchXor_##type(atomic_ptr, val, ATOMIC_MO_##order)
239#define CX_GENERATE_ATOMICS(type, short_type, lg_size) \
241 CX_ATOMIC_IL_ALIGN(lg_size) CX_ATOMIC_IL_REPR(lg_size) repr; \
242 } cx_atomic_##short_type; \
244 _meta_inline type _atomicLoad_##short_type(const cx_atomic_##short_type* a, \
245 AtmoicMemoryOrder mo) \
247 CX_ATOMIC_IL_REPR(lg_size) ret = CX_ATOMIC_IL_RAWLOAD(lg_size)(&a->repr); \
248 if (mo != ATOMIC_MO_Relaxed) { \
249 _atomicFence(ATOMIC_MO_Acquire); \
254 _meta_inline void _atomicStore_##short_type(cx_atomic_##short_type* a, \
256 AtmoicMemoryOrder mo) \
258 if (mo != ATOMIC_MO_Relaxed) { \
259 _atomicFence(ATOMIC_MO_Release); \
261 CX_ATOMIC_IL_RAWSTORE(lg_size)(&a->repr, (CX_ATOMIC_IL_REPR(lg_size))val); \
262 if (mo == ATOMIC_MO_SeqCst) { \
263 _atomicFence(ATOMIC_MO_SeqCst); \
268 _atomicExchange_##short_type(cx_atomic_##short_type* a, type val, AtmoicMemoryOrder mo) \
270 return (type)CX_ATOMIC_IL_NAME(_InterlockedExchange, \
271 lg_size)(&a->repr, (CX_ATOMIC_IL_REPR(lg_size))val); \
274 _meta_inline bool _atomicCompareExchange_weak_##short_type(cx_atomic_##short_type* a, \
277 AtmoicMemoryOrder success_mo, \
278 AtmoicMemoryOrder failure_mo) \
280 CX_ATOMIC_IL_REPR(lg_size) e = (CX_ATOMIC_IL_REPR(lg_size)) * expected; \
281 CX_ATOMIC_IL_REPR(lg_size) d = (CX_ATOMIC_IL_REPR(lg_size))desired; \
282 CX_ATOMIC_IL_REPR(lg_size) \
283 old = CX_ATOMIC_IL_NAME(_InterlockedCompareExchange, lg_size)(&a->repr, d, e); \
287 *expected = (type)old; \
292 _meta_inline bool _atomicCompareExchange_strong_##short_type(cx_atomic_##short_type* a, \
295 AtmoicMemoryOrder success_mo, \
296 AtmoicMemoryOrder failure_mo) \
299 return _atomicCompareExchange_weak_##short_type(a, \
306#define CX_EXTERN_ATOMICS(type, short_type) \
307 extern inline type _atomicLoad_##short_type(const cx_atomic_##short_type* a, \
308 AtmoicMemoryOrder mo); \
310 extern inline void _atomicStore_##short_type(cx_atomic_##short_type* a, \
312 AtmoicMemoryOrder mo); \
314 extern inline type _atomicExchange_##short_type(cx_atomic_##short_type* a, \
316 AtmoicMemoryOrder mo); \
318 extern inline bool _atomicCompareExchange_weak_##short_type(cx_atomic_##short_type* a, \
321 AtmoicMemoryOrder success_mo, \
322 AtmoicMemoryOrder failure_mo); \
324 extern inline bool _atomicCompareExchange_strong_##short_type(cx_atomic_##short_type* a, \
327 AtmoicMemoryOrder success_mo, \
328 AtmoicMemoryOrder failure_mo);
330#define CX_GENERATE_INT_ATOMICS(type, short_type, lg_size) \
331 CX_GENERATE_ATOMICS(type, short_type, lg_size) \
334 _atomicFetchAdd_##short_type(cx_atomic_##short_type* a, type val, AtmoicMemoryOrder mo) \
336 return (type)CX_ATOMIC_IL_NAME(_InterlockedExchangeAdd, \
337 lg_size)(&a->repr, (CX_ATOMIC_IL_REPR(lg_size))val); \
341 _atomicFetchSub_##short_type(cx_atomic_##short_type* a, type val, AtmoicMemoryOrder mo) \
347 __pragma(warning(push)) \
348 __pragma(warning(disable : 4146)) return _atomicFetchAdd_##short_type(a, -val, mo); \
349 __pragma(warning(pop)) \
352 _atomicFetchAnd_##short_type(cx_atomic_##short_type* a, type val, AtmoicMemoryOrder mo) \
354 return (type)CX_ATOMIC_IL_NAME(_InterlockedAnd, \
355 lg_size)(&a->repr, (CX_ATOMIC_IL_REPR(lg_size))val); \
358 _atomicFetchOr_##short_type(cx_atomic_##short_type* a, type val, AtmoicMemoryOrder mo) \
360 return (type)CX_ATOMIC_IL_NAME(_InterlockedOr, \
361 lg_size)(&a->repr, (CX_ATOMIC_IL_REPR(lg_size))val); \
364 _atomicFetchXor_##short_type(cx_atomic_##short_type* a, type val, AtmoicMemoryOrder mo) \
366 return (type)CX_ATOMIC_IL_NAME(_InterlockedXor, \
367 lg_size)(&a->repr, (CX_ATOMIC_IL_REPR(lg_size))val); \
370#define CX_EXTERN_INT_ATOMICS(type, short_type) \
371 CX_EXTERN_ATOMICS(type, short_type) \
373 extern inline type atomicFetchAdd_##short_type(cx_atomic_##short_type* a, \
375 AtmoicMemoryOrder mo); \
377 extern inline type atomicFetchSub_##short_type(cx_atomic_##short_type* a, \
379 AtmoicMemoryOrder mo); \
380 extern inline type atomicFetchAnd_##short_type(cx_atomic_##short_type* a, \
382 AtmoicMemoryOrder mo); \
383 extern inline type atomicFetchOr_##short_type(cx_atomic_##short_type* a, \
385 AtmoicMemoryOrder mo); \
386 extern inline type atomicFetchXor_##short_type(cx_atomic_##short_type* a, \
388 AtmoicMemoryOrder mo);