libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_preempt_involuntary.h
1/*-
2 * Copyright (c) 2026, The XTC Project -- All rights reserved.
3 * @stability experimental
4 * Use of this source code is governed by the ISC License.
5 *
6 * src/inc/xtc_preempt_involuntary.h
7 * Involuntary (signal-context) preemption: a timer tick that lands
8 * in a running fiber yields it to the scheduler at the interrupted
9 * instruction, so a loop-mate runs even while the fiber never reaches
10 * a yield point. EXPERIMENTAL (docs/abi-stability.md): the contract
11 * below may change in any minor release. The timer itself, and
12 * cooperative-assisted preemption, are in "xtc_preempt.h" (stable).
13 *
14 * THE CONTRACT (xtc_preempt_involuntary(3)):
15 * - A tick yields the fiber only at a SAFE POINT: outside a
16 * critical section and libxtc's own internal regions, and at a PC
17 * inside a PREEMPTIBLE range: every function marked
18 * XTC_PREEMPTIBLE, ranges added with xtc_preempt_region_add, and
19 * the main executable's own code when libxtc and libc are both
20 * shared objects. A static libxtc or libc lies inside the main
21 * text and cannot be told apart from it, so a STATIC BUILD MUST
22 * MARK ITS PREEMPTIBLE CODE (enabling with none fails). Never libc, other shared libraries, or
23 * libxtc itself: code compiled for a thread (malloc's per-thread
24 * cache, a FILE's per-thread lock) is not safe to interleave with a
25 * loop-mate on the same thread. Elsewhere the tick stays pending
26 * and the fiber yields at its next yield point.
27 * - The interrupted code resumes with its whole register file,
28 * flags, vector state, x87 state, PKRU and errno. The scheduler
29 * and the fibers it runs in the slice start from a call-boundary
30 * state (DF/AC clear, empty x87 stack, clean AVX upper halves; SME
31 * streaming mode and ZA off on aarch64).
32 * - Code in a preemptible range must not hold per-thread state a
33 * loop-mate could disturb (a thread-local scratch buffer, a lock
34 * that a loop-mate also takes) across instructions without a
35 * critical section (xtc_proc_critical_enter / _leave).
36 * - Linux x86-64 (ucontext; fcontext with glibc) and Linux aarch64
37 * only: xtc_preempt_involuntary_supported() says which. CET
38 * shadow stacks, AMX tile state and the aarch64 guarded control
39 * stack are not supported.
40 */
41
42#ifndef XTC_PREEMPT_INVOLUNTARY_H
43#define XTC_PREEMPT_INVOLUNTARY_H
44
45#include "xtc_export.h"
46
47#include "xtc.h"
48
49/*
50 * Mark a function preemptible: it is placed in the xtc_preemptible
51 * section, which the safe-point check trusts even in a static build
52 * (where the main text holds libxtc or libc and is not trusted). A marked function must follow the contract above; it may
53 * call anything, but a tick that lands in a callee outside a preemptible
54 * range is deferred. ELF with GCC or Clang; empty elsewhere.
55 */
56#if defined(__ELF__) && (defined(__GNUC__) || defined(__clang__))
57# define XTC_PREEMPTIBLE \
58 __attribute__((section("xtc_preemptible"), noinline))
59#else
60# define XTC_PREEMPTIBLE
61#endif
62
63/*
64 * PUBLIC: int xtc_preempt_set_involuntary __P((int));
65 * PUBLIC: int xtc_preempt_involuntary_supported __P((void));
66 * PUBLIC: int xtc_preempt_region_add __P((const void *, const void *));
67 */
68
69/* Enable (on != 0) or disable involuntary preemption, process-wide. It
70 * acts on threads whose preemption timer is armed (xtc_preempt_arm,
71 * xtc_exec_set_preempt). Off by default. Returns XTC_OK; enabling
72 * returns XTC_E_NOSYS, and leaves it off, where
73 * xtc_preempt_involuntary_supported() is 0 or no preemptible range can
74 * be trusted (a static executable with no XTC_PREEMPTIBLE function and
75 * no region added; adding one later lifts that refusal); the reason is
76 * reported once, at XTC_LOG_ERROR and on stderr. */
77XTC_API int xtc_preempt_set_involuntary(int on);
78
79/* 1 if this build and platform implement the involuntary redirect
80 * (Linux x86-64 on ucontext or glibc fcontext; Linux aarch64), else 0. */
81XTC_API int xtc_preempt_involuntary_supported(void);
82
83/* Add [start, end) to the preemptible ranges (code the application
84 * vouches for, e.g. a JIT buffer or a static build's own objects). Call
85 * before enabling. XTC_E_INVAL for an empty range or one overlapping
86 * libxtc's own text; XTC_E_RESOURCE when the table (32 ranges) is full.
87 * Ranges cannot be removed. */
88XTC_API int xtc_preempt_region_add(const void *start, const void *end);
89
90#endif /* XTC_PREEMPT_INVOLUNTARY_H */