libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
os_atomic.h
1/*-
2 * Copyright (c) 2026, The XTC Project
3 * Use of this source code is governed by the ISC License.
4 *
5 * src/inc/os_atomic.h
6 * Inline atomics over C11 <stdatomic.h>. Sequentially-consistent
7 * by default; no relaxed orderings exposed in M1.
8 *
9 * Variants are provided for int32_t, int64_t, uint32_t, uint64_t,
10 * and void*. See M1_CLAIMS.md, A1-A8.
11 */
12
13#ifndef XTC_OS_ATOMIC_H
14#define XTC_OS_ATOMIC_H
15
16#include <stdint.h>
17
18#if defined(__STDC_NO_ATOMICS__)
19# error "xtc requires C11 atomics; rebuild with a compiler that has <stdatomic.h>"
20#endif
21
22#include <stdatomic.h>
23
24/*
25 * The variable storing the atomic value is plain (non-_Atomic).
26 * We use atomic_*_explicit primitives applied to the address; this
27 * gives us the same ordering guarantees as _Atomic-qualified types
28 * and lets ordinary load/store work in single-threaded init paths
29 * before publication.
30 *
31 * Each macro takes a pointer-to-T as its first argument.
32 */
33
34#define __OS_ATOMIC_LOAD_DEFINE(suffix, T) \
35 static inline T \
36 __os_atomic_load_##suffix(const T *p) \
37 { \
38 return atomic_load_explicit( \
39 (_Atomic T *)(uintptr_t)p, \
40 memory_order_seq_cst); \
41 }
42
43#define __OS_ATOMIC_STORE_DEFINE(suffix, T) \
44 static inline void \
45 __os_atomic_store_##suffix(T *p, T v) \
46 { \
47 atomic_store_explicit( \
48 (_Atomic T *)p, v, memory_order_seq_cst); \
49 }
50
51#define __OS_ATOMIC_CAS_DEFINE(suffix, T) \
52 static inline int \
53 __os_atomic_cas_##suffix(T *p, T *expect, T desired) \
54 { \
55 return atomic_compare_exchange_strong_explicit( \
56 (_Atomic T *)p, expect, desired, \
57 memory_order_seq_cst, memory_order_seq_cst); \
58 }
59
60#define __OS_ATOMIC_FETCH_ADD_DEFINE(suffix, T) \
61 static inline T \
62 __os_atomic_fetch_add_##suffix(T *p, T delta) \
63 { \
64 return atomic_fetch_add_explicit( \
65 (_Atomic T *)p, delta, \
66 memory_order_seq_cst); \
67 }
68
69#define __OS_ATOMIC_DEFINE_ALL(suffix, T) \
70 __OS_ATOMIC_LOAD_DEFINE(suffix, T) \
71 __OS_ATOMIC_STORE_DEFINE(suffix, T) \
72 __OS_ATOMIC_CAS_DEFINE(suffix, T) \
73 __OS_ATOMIC_FETCH_ADD_DEFINE(suffix, T)
74
75__OS_ATOMIC_DEFINE_ALL(i32, int32_t)
76__OS_ATOMIC_DEFINE_ALL(i64, int64_t)
77__OS_ATOMIC_DEFINE_ALL(u32, uint32_t)
78__OS_ATOMIC_DEFINE_ALL(u64, uint64_t)
79
80/*
81 * Pointer atomics over intptr_t storage. Pointer-typed C11 atomics
82 * have surprisingly inconsistent codegen on some compilers; integer
83 * atomics are reliably correct.
84 */
85static inline void *
86__os_atomic_load_ptr(void *const *p)
87{
88 return (void *)(intptr_t)atomic_load_explicit(
89 (_Atomic intptr_t *)(uintptr_t)p, memory_order_seq_cst);
90}
91static inline void
92__os_atomic_store_ptr(void **p, void *v)
93{
94 atomic_store_explicit(
95 (_Atomic intptr_t *)p, (intptr_t)v, memory_order_seq_cst);
96}
97static inline int
98__os_atomic_cas_ptr(void **p, void **expect, void *desired)
99{
100 intptr_t e = (intptr_t)*expect;
101 int ok = atomic_compare_exchange_strong_explicit(
102 (_Atomic intptr_t *)p, &e, (intptr_t)desired,
103 memory_order_seq_cst, memory_order_seq_cst);
104 if (!ok) *expect = (void *)e;
105 return ok;
106}
107
108static inline void
109__os_atomic_fence(void)
110{
111 atomic_thread_fence(memory_order_seq_cst);
112}
113
114/*
115 * CPU spin hint. Not a syscall, not a yield. Tells the CPU we are
116 * spinning so it can throttle, save power, and avoid pipeline stalls
117 * on the lock release.
118 */
119#if defined(__x86_64__) || defined(__i386__)
120# define __os_pause() __asm__ __volatile__("pause" ::: "memory")
121#elif defined(__aarch64__)
122# define __os_pause() __asm__ __volatile__("yield" ::: "memory")
123#elif defined(__powerpc64__) || defined(__powerpc__)
124# define __os_pause() __asm__ __volatile__("or 27,27,27" ::: "memory")
125#else
126# define __os_pause() ((void)0)
127#endif
128
129#undef __OS_ATOMIC_DEFINE_ALL
130#undef __OS_ATOMIC_FETCH_ADD_DEFINE
131#undef __OS_ATOMIC_CAS_DEFINE
132#undef __OS_ATOMIC_STORE_DEFINE
133#undef __OS_ATOMIC_LOAD_DEFINE
134
135#endif /* XTC_OS_ATOMIC_H */