// 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
