libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
coro_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/coro_int.h
6 * Internal types for the L2 coroutine substrate.
7 */
8
9#ifndef XTC_CORO_INT_H
10#define XTC_CORO_INT_H
11
12#if defined(_WIN32)
13# include <windows.h>
14#elif defined(XTC_HAVE_UCONTEXT) && !defined(XTC_CORO_FORCE_FCTX) && \
15 !(defined(__APPLE__) && defined(__aarch64__) && \
16 !defined(XTC_CORO_FORCE_UCONTEXT) && !defined(XTC_AMALGAMATION))
17# include <ucontext.h>
18#endif
19
20#include "xtc_async.h"
21#include "loop_int.h"
22
23/*
24 * The fiber context attached to an xtc_task_t when it was spawned
25 * via xtc_async. Lives in the per-task arena (currently malloc).
26 */
27struct xtc_coro {
28#if defined(_WIN32)
29 LPVOID fiber; /* the coroutine's own Win32 fiber */
30 LPVOID loop_fiber; /* return-to-loop fiber pointer */
31#elif defined(XTC_HAVE_UCONTEXT) && !defined(XTC_CORO_FORCE_FCTX) && \
32 !(defined(__APPLE__) && defined(__aarch64__) && \
33 !defined(XTC_CORO_FORCE_UCONTEXT) && !defined(XTC_AMALGAMATION))
34 ucontext_t ctx; /* the coroutine's own machine state */
35 ucontext_t loop_ctx; /* return-to-loop context (set on resume) */
36#else
37 /* fcontext substrate (coro_fctx.c): a single saved stack pointer.
38 * On make_fcontext it is the fresh entry point; each yield/await
39 * overwrites it with the coroutine's current resume point. The
40 * scheduler's return point is a per-thread cursor in coro_fctx.c,
41 * not stored here, because coroutines always return to the
42 * scheduler, never directly to one another. */
43 void *fctx;
44#endif
45 void *stack;
46 size_t stack_sz;
47 xtc_coro_fn fn;
48 void *arg;
49 intptr_t result;
50 int done; /* 1 once fn has returned */
51
52 xtc_task_t *self; /* back-pointer to our task */
53 xtc_task_t *waiter; /* task awaiting this one (or NULL) */
54
55 /*
56 * When non-NULL, this coroutine has just registered itself as
57 * the `waiter` of another and is yielding into the loop with
58 * the intent of staying parked rather than rescheduling. The
59 * step function reads and clears this flag to decide between
60 * RESCHED and PENDING.
61 */
62 struct xtc_coro *_parked_on;
63
64 /*
65 * Sanitizer fiber-switch save token (ASan/TSan/LSan). Holds this
66 * coro's "fake stack" across a park so __sanitizer_start/finish_
67 * switch_fiber can track the user-space stack switch and stop
68 * mis-attributing stack memory. Unused (always NULL) in a
69 * non-sanitized build. See XTC_FIBER_SWITCH_ANNOTATE in
70 * coro_fctx.c / coro_uctx.c.
71 */
72 void *san_fake_stack;
73
74 /*
75 * TSan fiber-IDENTITY token (clang ThreadSanitizer only). TSan
76 * does NOT implement __sanitizer_*_switch_fiber; it needs each
77 * coroutine represented as a TSan "fiber object" (__tsan_create_
78 * fiber at create, __tsan_switch_to_fiber at every switch,
79 * __tsan_destroy_fiber at teardown) so it can carry per-fiber
80 * happens-before across cooperative switches instead of seeing
81 * them as one confused thread. Distinct from san_fake_stack (the
82 * two sanitizer models are mutually exclusive per build). Always
83 * NULL unless built with clang -fsanitize=thread. See
84 * XTC_TSAN_FIBERS in coro_fctx.c / coro_uctx.c.
85 */
86 void *tsan_fiber;
87};
88
89/* Shared by loop.c -- the currently-running coroutine on this loop. */
90extern XTC_THREAD_LOCAL struct xtc_coro *__xtc_current_coro;
91
92/* Forward declarations for the dispatch glue. */
93int __xtc_coro_step(xtc_task_t *self, void *user);
94
95/*
96 * Internal spawn with an explicit pin flag. The public xtc_async wraps
97 * this with pinned=1 (the long-standing default: a coro's task is not
98 * work-stealable). pinned=0 places the task on the stealable deque so
99 * it can migrate across loops -- used by the proc layer when
100 * xtc_proc_opts_t.migratable is set. Every coro backend
101 * (coro_fctx/uctx/winfiber) defines it.
102 */
103int __xtc_async_ex(xtc_loop_t *loop, xtc_coro_fn fn, void *arg, int pinned,
104 xtc_task_t **out_task);
105
106/* The task wrapping the currently-running coroutine on this thread,
107 * or NULL when not running inside a coroutine. Lets lower-level
108 * primitives (e.g. xtc_amutex) find the current task to park it. */
109xtc_task_t *__xtc_current_task(void);
110
111#endif /* XTC_CORO_INT_H */