libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
aio_int.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/aio_int.h
6 * Internal xtc_aio helpers. __xtc_aio_force_offload forces
7 * the blocking-pool offload path even on a host with a native
8 * completion engine (io_uring / IOCP), so the portable fallback can
9 * be exercised and proven identical to the native path. Also reads
10 * XTC_AIO_FORCE_OFFLOAD=1 on first use. __xtc_aio_done_set/_get are
11 * the atomic accessors for the cross-thread xtc_aio_t.done completion
12 * flag (see the contract comment below). Library-internal (the __
13 * prefix) and not part of the stable API -- split out of xtc_aio.h
14 * so no __-prefixed symbol leaks into an installed public header.
15 */
16
17#ifndef XTC_AIO_INT_H
18#define XTC_AIO_INT_H
19
20#include "xtc_io.h" /* xtc_aio_t */
21
22#include <stdatomic.h>
23
24void __xtc_aio_force_offload(int on);
25
26/*
27 * Cross-thread access to xtc_aio_t.done.
28 *
29 * On a native completion backend the REAPING thread (whichever loop's poll
30 * thread drains the ring) publishes the result and the PARKED FIBER reads it
31 * in its wake-recheck loop. Two threads, one flag: the accesses must be
32 * atomic, and the flag must ORDER the result field it guards.
33 *
34 * The field itself stays a plain `int` -- see the contract comment on
35 * xtc_aio_t.done in xtc_io.h for why (public header, C++ consumers, and a
36 * measured-identical layout either way). These helpers apply C11 atomics to
37 * its ADDRESS, the pattern src/inc/os_atomic.h is built around.
38 *
39 * Ordering is release/acquire, not seq_cst, and that is the point: the
40 * reaper writes a->res and THEN releases a->done, so a fiber that acquires a
41 * set done is guaranteed to see the matching res. Before this, res was read
42 * after a PLAIN done read with nothing ordering the two -- the scheduler
43 * handoff (the wake CAS / inbox mutex) does supply an edge, but the recheck
44 * loop can observe done through its own read WITHOUT going through that
45 * edge, so the handoff did not actually cover this pair. Same publish-
46 * result-then-flag shape, and same ordering, as w->result / w->done in
47 * src/ptc/blocking.c.
48 *
49 * The clearing store on the submit path is deliberately NOT routed here: it
50 * runs on the submitting fiber's own thread before the op is visible to any
51 * reaper, which is exactly the single-threaded pre-publication case plain
52 * storage exists to allow.
53 */
54static inline void
55__xtc_aio_done_set(xtc_aio_t *a)
56{
57 atomic_store_explicit((_Atomic int *)&a->done, 1,
58 memory_order_release);
59}
60
61static inline int
62__xtc_aio_done_get(const xtc_aio_t *a)
63{
64 return atomic_load_explicit(
65 (_Atomic int *)(uintptr_t)&a->done, memory_order_acquire);
66}
67
68#endif /* XTC_AIO_INT_H */