libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_preempt.h
1/*-
2 * Copyright (c) 2026, The XTC Project -- All rights reserved.
3 * Use of this source code is governed by the ISC License.
4 *
5 * src/inc/xtc_preempt.h
6 * Per-worker preemption timer seam.
7 *
8 * Phase 0 (this): a per-thread CPU-time interval timer whose handler
9 * records a tick. No preemption yet -- the seam later phases build
10 * on. OFF by default (nothing arms it unless xtc_preempt_arm is
11 * called); the cooperative fast path is unchanged when unused.
12 */
13
14#ifndef XTC_PREEMPT_H
15#define XTC_PREEMPT_H
16
17#include <stdint.h>
18#include <pthread.h>
19
20#include "xtc.h"
21
22/*
23 * Arm a per-thread preemption timer that fires every `interval_ns` of
24 * THIS thread's CPU time (not wall time), delivering SIGVTALRM to this
25 * thread. Idempotent re-arm re-sets the interval. Returns XTC_OK, or
26 * XTC_E_NOSYS where POSIX per-thread CPU-time timers are unavailable, or
27 * XTC_E_INVAL for interval_ns <= 0. Call from the worker thread it
28 * should time.
29 *
30 * PUBLIC: int xtc_preempt_arm __P((int64_t));
31 * PUBLIC: int xtc_preempt_disarm __P((void));
32 * PUBLIC: int xtc_preempt_supported __P((void));
33 * PUBLIC: uint64_t xtc_preempt_ticks __P((void));
34 * PUBLIC: int xtc_preempt_tick_pending __P((void));
35 */
36int xtc_preempt_arm(int64_t interval_ns);
37
38/* Stop + delete this thread's preemption timer. Safe if not armed. */
39int xtc_preempt_disarm(void);
40
41/* Enable (on != 0) / disable signal-context involuntary yield (Phase
42 * 2). When on and the timer is armed, a tick preempts the running
43 * fiber in the handler -- resumably and only when safe (crit_depth ==
44 * 0, unsafe_depth == 0) -- on the ucontext substrate; the fctx/winfiber
45 * substrate declines and falls back to cooperative-assisted preemption.
46 * Off by default.
47 *
48 * PUBLIC: void xtc_preempt_set_involuntary __P((int));
49 */
50void xtc_preempt_set_involuntary(int on);
51
52/* 1 if per-thread CPU-time preemption timers are available on this
53 * platform, 0 otherwise (arm returns NOSYS then). */
54int xtc_preempt_supported(void);
55
56/* Total timer ticks this thread has observed since arming (Phase 0
57 * seam-works metric / telemetry). */
58uint64_t xtc_preempt_ticks(void);
59
60/* 1 if a timer tick fired and is unconsumed; consumes (clears) it.
61 * Phase 1 consults this at safe points to decide whether to yield. */
62int xtc_preempt_tick_pending(void);
63
64/*
65 * Async-signal-unsafe-region depth (Phase 2 prerequisite). A per-thread
66 * nesting counter that is > 0 while the thread is inside an
67 * async-signal-unsafe region (the allocator, a latch's internal lock).
68 * The preemption timer handler must not do a signal-context involuntary
69 * yield while it is > 0 (it defers). __xtc_unsafe_enter/leave bracket
70 * such a region; __xtc_unsafe_depth reads the current depth (also used
71 * by the fault handler so a SIGSEGV inside malloc does not unwind out of
72 * a corrupt arena).
73 *
74 * PUBLIC: void __xtc_unsafe_enter __P((void));
75 * PUBLIC: void __xtc_unsafe_leave __P((void));
76 * PUBLIC: int __xtc_unsafe_depth __P((void));
77 */
78void __xtc_unsafe_enter(void);
79void __xtc_unsafe_leave(void);
80int __xtc_unsafe_depth(void);
81
82/*
83 * Preemption-safe raw-pthread mutex brackets. A fiber that holds a
84 * mutex must not be involuntarily preempted (a loop runs many fibers on
85 * one OS thread; a preempted holder plus another same-loop fiber
86 * blocking on the same mutex deadlocks the thread). __xtc_mtx_lock/
87 * unlock wrap pthread_mutex_lock/unlock with __xtc_unsafe_enter/leave
88 * so the preemption timer defers while the lock is held -- the
89 * raw-pthread counterpart of the preemption-safe __os_mutex_* locks,
90 * for internal subsystems that embed a bare pthread_mutex_t. Use only
91 * for short critical sections that do NOT yield/park while holding the
92 * lock. They return the raw pthread errno (0 == success).
93 */
94int __xtc_mtx_lock(pthread_mutex_t *m);
95int __xtc_mtx_unlock(pthread_mutex_t *m);
96
97#endif /* XTC_PREEMPT_H */