65816-llvm-mos/runtime/include/stdatomic.h
Scott Duensing e65fedc8e1 Checkpoint
2026-05-13 15:48:34 -05:00

138 lines
5 KiB
C

// 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 <stddef.h>
#include <stdint.h>
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