24#ifndef NEXUS_ARCH_ATOMIC_H
25#define NEXUS_ARCH_ATOMIC_H
30#if !(defined(__GNUC__) || defined(__clang__))
31#error "Nexus inline atomics require the maintained GCC/Clang compiler port"
35static_assert(
sizeof(uint32_t) == 4 &&
sizeof(unsigned) == 4 && CHAR_BIT == 8,
36 "Nexus atomics require naturally aligned 32-bit unsigned words");
38_Static_assert(
sizeof(uint32_t) == 4 &&
sizeof(unsigned) == 4 && CHAR_BIT == 8,
39 "Nexus atomics require naturally aligned 32-bit unsigned words");
42#if defined(__ARM_ARCH_6M__)
44#elif __GCC_ATOMIC_INT_LOCK_FREE != 2
45#error "Nexus RMW requires lock-free words or the reviewed ARMv6-M IRQ port"
49static inline uint32_t nx_atomic_u32_load_relaxed(
const uint32_t* value) {
50 return __atomic_load_n(value, __ATOMIC_RELAXED);
54static inline uint32_t nx_atomic_u32_load_acquire(
const uint32_t* value) {
55 return __atomic_load_n(value, __ATOMIC_ACQUIRE);
59static inline void nx_atomic_u32_store_relaxed(uint32_t* value,
61 __atomic_store_n(value, desired, __ATOMIC_RELAXED);
65static inline void nx_atomic_u32_store_release(uint32_t* value,
67 __atomic_store_n(value, desired, __ATOMIC_RELEASE);
70#if defined(__ARM_ARCH_6M__)
75static inline uint32_t nx_atomic_u32_add_guarded(uint32_t* value,
78 uint32_t observed = nx_atomic_u32_load_acquire(value);
79 nx_atomic_u32_store_release(value, (uint32_t)(observed + amount));
96static inline bool nx_atomic_u32_compare_exchange_acq_rel(uint32_t* value,
99#if defined(__ARM_ARCH_6M__)
101 uint32_t observed = nx_atomic_u32_load_acquire(value);
102 bool matched = observed == *expected;
104 nx_atomic_u32_store_release(value, desired);
106 *expected = observed;
111 return __atomic_compare_exchange_n(value, expected, desired,
false,
112 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
118static inline uint32_t nx_atomic_u32_fetch_add_acq_rel(uint32_t* value,
120#if defined(__ARM_ARCH_6M__)
121 return nx_atomic_u32_add_guarded(value, amount);
123 return __atomic_fetch_add(value, amount, __ATOMIC_ACQ_REL);
131static inline uint32_t nx_atomic_u32_fetch_add_release(uint32_t* value,
133#if defined(__ARM_ARCH_6M__)
134 return nx_atomic_u32_add_guarded(value, amount);
136 return __atomic_fetch_add(value, amount, __ATOMIC_RELEASE);
143static inline uint32_t nx_atomic_u32_fetch_sub_acq_rel(uint32_t* value,
145#if defined(__ARM_ARCH_6M__)
146 return nx_atomic_u32_add_guarded(value, (uint32_t)(0u - amount));
148 return __atomic_fetch_sub(value, amount, __ATOMIC_ACQ_REL);
156static inline uint32_t nx_atomic_u32_fetch_sub_release(uint32_t* value,
158#if defined(__ARM_ARCH_6M__)
159 return nx_atomic_u32_add_guarded(value, (uint32_t)(0u - amount));
161 return __atomic_fetch_sub(value, amount, __ATOMIC_RELEASE);
CPU-local mask, context, ordering and cycle snapshot contract.
void nx_arch_irq_restore(nx_arch_irq_state_t previous)
Restore the incoming mask, preserving nested exclusions.
nx_arch_irq_state_t nx_arch_irq_save(void)
Save incoming local mask and mask configurable exceptions.
Saved incoming PRIMASK or calling-thread Native nesting.