// stdatomic.h — C11 atomic operations, single-core stubs. // // The W65816 is a uniprocessor with no preemption from a kernel scheduler // (we run bare on the IIgs, optionally under GS/OS which doesn't yield // inside a process). All `atomic_*` operations lower to plain ops; the // `memory_order_*` constants are accepted and ignored. // // This header provides the C11 API surface so portable code that uses // `_Atomic int` / `atomic_fetch_add` / etc. compiles cleanly. Real // multi-core atomicity is not modeled. #ifndef _STDATOMIC_H #define _STDATOMIC_H #include #include typedef enum { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst } memory_order; #define ATOMIC_BOOL_LOCK_FREE 1 #define ATOMIC_CHAR_LOCK_FREE 1 #define ATOMIC_CHAR16_T_LOCK_FREE 1 #define ATOMIC_CHAR32_T_LOCK_FREE 1 #define ATOMIC_WCHAR_T_LOCK_FREE 1 #define ATOMIC_SHORT_LOCK_FREE 1 #define ATOMIC_INT_LOCK_FREE 1 #define ATOMIC_LONG_LOCK_FREE 1 #define ATOMIC_LLONG_LOCK_FREE 1 #define ATOMIC_POINTER_LOCK_FREE 1 #define ATOMIC_VAR_INIT(v) (v) #define ATOMIC_FLAG_INIT { 0 } // Atomic flag — a boolean-valued atomic flag. typedef struct { volatile unsigned char _v; } atomic_flag; static inline int atomic_flag_test_and_set_explicit(volatile atomic_flag *o, memory_order m) { (void)m; int r = o->_v; o->_v = 1; return r; } static inline int atomic_flag_test_and_set(volatile atomic_flag *o) { return atomic_flag_test_and_set_explicit(o, memory_order_seq_cst); } static inline void atomic_flag_clear_explicit(volatile atomic_flag *o, memory_order m) { (void)m; o->_v = 0; } static inline void atomic_flag_clear(volatile atomic_flag *o) { atomic_flag_clear_explicit(o, memory_order_seq_cst); } // Thread-fence — no-op on a uniprocessor with no kernel preemption. static inline void atomic_thread_fence(memory_order m) { (void)m; } static inline void atomic_signal_fence(memory_order m) { (void)m; } // _Atomic(T) is just T on this target. Generic load/store/RMW macros // delegate to plain ops. Uses __typeof__ to preserve type info. #define atomic_init(obj, val) (*(obj) = (val)) #define atomic_is_lock_free(obj) ((void)(obj), 1) #define atomic_store(obj, val) (*(obj) = (val)) #define atomic_store_explicit(obj, val, m) ((void)(m), *(obj) = (val)) #define atomic_load(obj) (*(obj)) #define atomic_load_explicit(obj, m) ((void)(m), *(obj)) #define atomic_exchange(obj, val) ({ \ __typeof__(*(obj)) _old = *(obj); \ *(obj) = (val); \ _old; }) #define atomic_exchange_explicit(obj, val, m) \ ((void)(m), atomic_exchange(obj, val)) #define atomic_compare_exchange_strong(obj, expected, desired) ({ \ int _ok = (*(obj) == *(expected)); \ if (_ok) *(obj) = (desired); else *(expected) = *(obj); \ _ok; }) #define atomic_compare_exchange_weak(obj, expected, desired) \ atomic_compare_exchange_strong(obj, expected, desired) #define atomic_compare_exchange_strong_explicit(obj, expected, desired, ms, mf) \ ((void)(ms), (void)(mf), \ atomic_compare_exchange_strong(obj, expected, desired)) #define atomic_compare_exchange_weak_explicit(obj, expected, desired, ms, mf) \ ((void)(ms), (void)(mf), \ atomic_compare_exchange_weak(obj, expected, desired)) #define atomic_fetch_add(obj, val) ({ \ __typeof__(*(obj)) _old = *(obj); \ *(obj) += (val); \ _old; }) #define atomic_fetch_add_explicit(obj, val, m) \ ((void)(m), atomic_fetch_add(obj, val)) #define atomic_fetch_sub(obj, val) ({ \ __typeof__(*(obj)) _old = *(obj); \ *(obj) -= (val); \ _old; }) #define atomic_fetch_sub_explicit(obj, val, m) \ ((void)(m), atomic_fetch_sub(obj, val)) #define atomic_fetch_or(obj, val) ({ \ __typeof__(*(obj)) _old = *(obj); \ *(obj) |= (val); \ _old; }) #define atomic_fetch_or_explicit(obj, val, m) \ ((void)(m), atomic_fetch_or(obj, val)) #define atomic_fetch_and(obj, val) ({ \ __typeof__(*(obj)) _old = *(obj); \ *(obj) &= (val); \ _old; }) #define atomic_fetch_and_explicit(obj, val, m) \ ((void)(m), atomic_fetch_and(obj, val)) #define atomic_fetch_xor(obj, val) ({ \ __typeof__(*(obj)) _old = *(obj); \ *(obj) ^= (val); \ _old; }) #define atomic_fetch_xor_explicit(obj, val, m) \ ((void)(m), atomic_fetch_xor(obj, val)) // _Atomic-qualified typedefs that portable C11 code expects. typedef _Bool atomic_bool; typedef char atomic_char; typedef signed char atomic_schar; typedef unsigned char atomic_uchar; typedef short atomic_short; typedef unsigned short atomic_ushort; typedef int atomic_int; typedef unsigned int atomic_uint; typedef long atomic_long; typedef unsigned long atomic_ulong; typedef long long atomic_llong; typedef unsigned long long atomic_ullong; #endif