libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_inject.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/xtc_inject.h
6 * Injection points: named locations in production code that
7 * can be intercepted by tests to drive the runtime to a
8 * specific state and pause/resume execution from outside.
9 *
10 * Three operations on a named point at runtime:
11 * ATTACH bind a callback (or "wait" semantics) to the name
12 * DETACH remove
13 * TRIGGER hit the point -- the macro INJECTION_POINT(name) in
14 * production code calls into this
15 *
16 * When TRIGGER fires:
17 * - if no callback attached, no-op (production fast-path)
18 * - if a callback is attached, it runs synchronously in the
19 * triggering proc/thread
20 * - if "wait" is attached, the trigger blocks on a condition
21 * variable until inject_wakeup(name) is called from a
22 * test thread
23 *
24 * Compile-time gating: define `XTC_INJECT_DISABLE` to elide
25 * all INJECTION_POINT(...) calls to a no-op. Default: enabled.
26 * (PG defaults to disabled in non-debug builds.)
27 *
28 * Per-name max attached callbacks: 4. Names are fixed-size
29 * (64 bytes including NUL).
30 */
31
32#ifndef XTC_INJECT_H
33#define XTC_INJECT_H
34
35#include <stddef.h>
36#include <stdint.h>
37
38#include "xtc.h"
39
40#define XTC_INJECT_NAME_MAX 64
41
42typedef void (*xtc_inject_fn)(const char *name, void *user);
43
44/*
45 * PUBLIC: int xtc_inject_attach __P((const char *, xtc_inject_fn, void *));
46 * PUBLIC: int xtc_inject_attach_wait __P((const char *));
47 * PUBLIC: int xtc_inject_detach __P((const char *));
48 * PUBLIC: void xtc_inject_trigger __P((const char *));
49 * PUBLIC: int xtc_inject_wakeup __P((const char *));
50 * PUBLIC: int xtc_inject_n_attached __P((void));
51 * PUBLIC: int xtc_inject_check __P((const char *));
52 */
53
54/* Attach a callback. Multiple attaches accumulate (up to 4 per
55 * name). Returns XTC_E_RESOURCE if the slot table is full. */
56int xtc_inject_attach(const char *name, xtc_inject_fn fn, void *user);
57
58/* Attach "wait" semantics: when the point fires, block until
59 * xtc_inject_wakeup(name) is called. Useful for racing tests. */
60int xtc_inject_attach_wait(const char *name);
61
62/* Detach all attachments for a name. */
63int xtc_inject_detach(const char *name);
64
65/* Trigger from production code. Internal -- usually called via the
66 * INJECTION_POINT() macro below, which compiles to a no-op when
67 * XTC_INJECT_DISABLE is set. */
68void xtc_inject_trigger(const char *name);
69
70/* Release a "wait" attachment so the triggering thread can proceed. */
71int xtc_inject_wakeup(const char *name);
72
73/* Diagnostics: how many names currently have attachments. */
74int xtc_inject_n_attached(void);
75
76/* Lock-free check: 1 if `name` has any attachments, 0 otherwise.
77 * Hot-path-friendly: when no inject points are attached anywhere,
78 * this returns 0 immediately via an atomic load. */
79int xtc_inject_check(const char *name);
80
81/* The macro production code uses. In PG-style this is INJECTION_POINT;
82 * we use XTC_INJECTION_POINT so caller code reading a stack trace
83 * sees the namespace immediately. */
84#if defined(XTC_INJECT_DISABLE)
85# define XTC_INJECTION_POINT(name) ((void)0)
86#else
87# define XTC_INJECTION_POINT(name) xtc_inject_trigger(name)
88#endif
89
90#endif /* XTC_INJECT_H */