xtc_preempt(3)

---

xtc_preempt(3)

per-worker preemption timer seam

XTC_PREEMPT(3) Library Functions Manual XTC_PREEMPT(3)

xtc_preempt_arm, xtc_preempt_disarm, xtc_preempt_supported, xtc_preempt_ticks, xtc_preempt_tick_pendingper-worker preemption timer seam

#include <xtc_preempt.h>

int
xtc_preempt_arm(int64_t interval_ns);

int
xtc_preempt_disarm(void);

int
xtc_preempt_supported(void);

uint64_t
xtc_preempt_ticks(void);

int
xtc_preempt_tick_pending(void);

These functions manage a per-thread preemption timer -- the seam the libxtc preemption facility is built on (see the preemption design in the project docs). The timer measures the calling thread's own CPU time, so a busy fiber accrues ticks while an idle worker does not.

() arms a timer on the calling thread that fires every interval_ns of that thread's CPU time, delivering an internal signal to the thread. Re-arming re-sets the interval. It returns XTC_OK, XTC_E_INVAL for a non-positive interval, or XTC_E_NOSYS where per-thread CPU-time timers are unavailable.

() stops and deletes the calling thread's timer; it is safe to call when no timer is armed.

() returns non-zero where the platform provides per-thread CPU-time timers (Linux, the BSDs, illumos, AIX) and zero otherwise, in which case xtc_preempt_arm() returns XTC_E_NOSYS.

() returns the total number of timer ticks the calling thread has observed since arming -- telemetry, and the metric that confirms the seam works.

() returns non-zero if a tick has fired and is unconsumed, clearing the flag. The cooperative-assisted preemption path consults it at safe points to decide whether to yield.

The int functions return XTC_OK on success or a negative XTC_E_* code as described above.

The timer only records ticks; it does not by itself preempt a running fiber. Higher layers of the preemption facility act on the ticks -- cooperatively (a yield at the next safe point) or, when the involuntary path is enabled, via a signal-context involuntary yield. Nothing arms the timer unless a caller opts in, so the cooperative fast path is unchanged when unused.

The involuntary path (enabled by ()) is EXPERIMENTAL and off by default. On x86-64 with the ucontext coroutine substrate (the default build on glibc) it performs a true resumable involuntary yield -- a fiber in a pure CPU loop with no cooperative yield points is time-sliced so its loop-mates make progress -- using an on-stack trampoline that the signal handler redirects the interrupted instruction pointer to (Go's async-preemption method). On other substrates (the fcontext substrate used on musl, the Windows fiber substrate) and in the single-file amalgamation it declines and falls back to the cooperative path. It is opt-in because a rare livelock has been observed under pathological all-CPU-bound load; untrusted pure-CPU work can alternatively run on xtc_osproc(3), an operating-system thread the kernel preempts.

xtc_async(3), xtc_exec(3), xtc_osproc(3)

The XTC Project.

July 1, 2026 Debian

View the mdoc source