8#ifndef UPB_PORT_ATOMIC_H_
9#define UPB_PORT_ATOMIC_H_
13#ifdef UPB_USE_C11_ATOMICS
20#define upb_Atomic_Init(addr, val) atomic_init(addr, val)
21#define upb_Atomic_Load(addr, order) atomic_load_explicit(addr, order)
22#define upb_Atomic_Store(addr, val, order) \
23 atomic_store_explicit(addr, val, order)
24#define upb_Atomic_Exchange(addr, val, order) \
25 atomic_exchange_explicit(addr, val, order)
26#define upb_Atomic_CompareExchangeStrong(addr, expected, desired, \
27 success_order, failure_order) \
28 atomic_compare_exchange_strong_explicit(addr, expected, desired, \
29 success_order, failure_order)
30#define upb_Atomic_CompareExchangeWeak(addr, expected, desired, success_order, \
32 atomic_compare_exchange_weak_explicit(addr, expected, desired, \
33 success_order, failure_order)
35#elif defined(UPB_USE_MSC_ATOMICS)
40#define upb_Atomic_Init(addr, val) (*(addr) = val)
45#pragma intrinsic(_InterlockedExchange64)
46#define upb_Atomic_Store(addr, val, order) \
47 (void)_InterlockedExchange64((uint64_t volatile *)addr, (uint64_t)val)
49#pragma intrinsic(_InterlockedCompareExchange64)
50static uintptr_t upb_Atomic_LoadMsc(uint64_t
volatile *addr) {
53 return _InterlockedCompareExchange64(addr, 0xDEADC0DEBAADF00D,
58#if __STDC_VERSION__ >= 201112L
59#define upb_Atomic_Load(addr, order) \
61 UPB_ATOMIC(uintptr_t) *: upb_Atomic_LoadMsc( \
62 (uint64_t volatile *)(addr)), \
63 default: (void *)upb_Atomic_LoadMsc((uint64_t volatile *)(addr)))
65#define upb_Atomic_Exchange(addr, val, order) \
67 UPB_ATOMIC(uintptr_t) *: _InterlockedExchange64( \
68 (uint64_t volatile *)(addr), (uint64_t)val), \
69 default: (void *)_InterlockedExchange64((uint64_t volatile *)addr, \
74#define upb_Atomic_Load(addr, order) \
75 (void *)upb_Atomic_LoadMsc((uint64_t volatile *)(addr))
77#define upb_Atomic_Exchange(addr, val, order) \
78 (void *)_InterlockedExchange64((uint64_t volatile *)addr, (uint64_t)val)
81#pragma intrinsic(_InterlockedCompareExchange64)
82static bool upb_Atomic_CompareExchangeMscP(uint64_t
volatile *addr,
85 uint64_t expect_val = *expected;
87 _InterlockedCompareExchange64(addr, desired, expect_val);
88 if (expect_val != actual_val) {
89 *expected = actual_val;
95#define upb_Atomic_CompareExchangeStrong(addr, expected, desired, \
96 success_order, failure_order) \
97 upb_Atomic_CompareExchangeMscP((uint64_t volatile *)addr, \
98 (uint64_t *)expected, (uint64_t)desired)
100#define upb_Atomic_CompareExchangeWeak(addr, expected, desired, success_order, \
102 upb_Atomic_CompareExchangeMscP((uint64_t volatile *)addr, \
103 (uint64_t *)expected, (uint64_t)desired)
106#pragma intrinsic(_InterlockedExchange)
107#define upb_Atomic_Store(addr, val, order) \
108 (void)_InterlockedExchange((uint32_t volatile *)addr, (uint32_t)val)
110#pragma intrinsic(_InterlockedCompareExchange)
111static uintptr_t upb_Atomic_LoadMsc(uint32_t
volatile *addr) {
114 return _InterlockedCompareExchange(addr, 0xDEADC0DE, 0xDEADC0DE);
118#if __STDC_VERSION__ >= 201112L
119#define upb_Atomic_Load(addr, order) \
121 UPB_ATOMIC(uintptr_t) *: upb_Atomic_LoadMsc( \
122 (uint32_t volatile *)(addr)), \
123 default: (void *)upb_Atomic_LoadMsc((uint32_t volatile *)(addr)))
125#define upb_Atomic_Exchange(addr, val, order) \
127 UPB_ATOMIC(uintptr_t) *: _InterlockedExchange( \
128 (uint32_t volatile *)(addr), (uint32_t)val), \
129 default: (void *)_InterlockedExchange64((uint32_t volatile *)addr, \
132#define upb_Atomic_Load(addr, order) \
133 (void *)upb_Atomic_LoadMsc((uint32_t volatile *)(addr))
135#define upb_Atomic_Exchange(addr, val, order) \
136 (void *)_InterlockedExchange((uint32_t volatile *)addr, (uint32_t)val)
139#pragma intrinsic(_InterlockedCompareExchange)
140static bool upb_Atomic_CompareExchangeMscP(uint32_t
volatile *addr,
143 uint32_t expect_val = *expected;
144 uint32_t actual_val = _InterlockedCompareExchange(addr, desired, expect_val);
145 if (expect_val != actual_val) {
146 *expected = actual_val;
152#define upb_Atomic_CompareExchangeStrong(addr, expected, desired, \
153 success_order, failure_order) \
154 upb_Atomic_CompareExchangeMscP((uint32_t volatile *)addr, \
155 (uint32_t *)expected, (uint32_t)desired)
157#define upb_Atomic_CompareExchangeWeak(addr, expected, desired, success_order, \
159 upb_Atomic_CompareExchangeMscP((uint32_t volatile *)addr, \
160 (uint32_t *)expected, (uint32_t)desired)
165#if !defined(UPB_SUPPRESS_MISSING_ATOMICS)
167#error Your compiler does not support atomic instructions, which UPB uses. If you do not use UPB on multiple threads, you can suppress this error by defining UPB_SUPPRESS_MISSING_ATOMICS.
172#define upb_Atomic_Init(addr, val) (*addr = val)
173#define upb_Atomic_Load(addr, order) (*addr)
174#define upb_Atomic_Store(addr, val, order) (*(addr) = val)
178 memcpy(&old, addr,
sizeof(value));
179 memcpy(addr, &value,
sizeof(value));
183#define upb_Atomic_Exchange(addr, val, order) _upb_NonAtomic_Exchange(addr, val)
189 if (memcmp(addr, expected,
sizeof(desired)) == 0) {
190 memcpy(addr, &desired,
sizeof(desired));
193 memcpy(expected, addr,
sizeof(desired));
198#define upb_Atomic_CompareExchangeStrong(addr, expected, desired, \
199 success_order, failure_order) \
200 _upb_NonAtomic_CompareExchangeStrongP((void*)addr, (void*)expected, \
202#define upb_Atomic_CompareExchangeWeak(addr, expected, desired, success_order, \
204 upb_Atomic_CompareExchangeStrong(addr, expected, desired, 0, 0)
UPB_INLINE void * _upb_NonAtomic_Exchange(void *addr, void *value)
Definition atomic.h:176
UPB_INLINE bool _upb_NonAtomic_CompareExchangeStrongP(void *addr, void *expected, void *desired)
Definition atomic.h:186
#define UPB_INLINE
Definition def.inc:144
uint128_t uintptr_t
Definition format.h:418