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 "xtc_export.h"
36
37#include <stddef.h>
38#include <stdint.h>
39
40#include "xtc.h"
41
42#define XTC_INJECT_NAME_MAX 64
43
44typedef void (*xtc_inject_fn)(const char *name, void *user);
45
46/*
47 * PUBLIC: int xtc_inject_attach __P((const char *, xtc_inject_fn, void *));
48 * PUBLIC: int xtc_inject_attach_wait __P((const char *));
49 * PUBLIC: int xtc_inject_detach __P((const char *));
50 * PUBLIC: void xtc_inject_trigger __P((const char *));
51 * PUBLIC: int xtc_inject_wakeup __P((const char *));
52 * PUBLIC: int xtc_inject_n_attached __P((void));
53 * PUBLIC: int xtc_inject_check __P((const char *));
54 */
55
56/* Attach a callback. Multiple attaches accumulate (up to 4 per
57 * name). Returns XTC_E_RESOURCE if the slot table is full. */
58XTC_API int xtc_inject_attach(const char *name, xtc_inject_fn fn, void *user);
59
60/* Attach "wait" semantics: when the point fires, block until
61 * xtc_inject_wakeup(name) is called. Useful for racing tests. */
62XTC_API int xtc_inject_attach_wait(const char *name);
63
64/* Detach all attachments for a name. */
65XTC_API int xtc_inject_detach(const char *name);
66
67/* Trigger from production code. Internal -- usually called via the
68 * INJECTION_POINT() macro below, which compiles to a no-op when
69 * XTC_INJECT_DISABLE is set. */
70XTC_API void xtc_inject_trigger(const char *name);
71
72/* Release a "wait" attachment so the triggering thread can proceed. */
73XTC_API int xtc_inject_wakeup(const char *name);
74
75/* Diagnostics: how many names currently have attachments. */
76XTC_API int xtc_inject_n_attached(void);
77
78/* Lock-free check: 1 if `name` has any attachments, 0 otherwise.
79 * Hot-path-friendly: when no inject points are attached anywhere,
80 * this returns 0 immediately via an atomic load. */
81XTC_API int xtc_inject_check(const char *name);
82
83/* The macro production code uses. In PG-style this is INJECTION_POINT;
84 * we use XTC_INJECTION_POINT so caller code reading a stack trace
85 * sees the namespace immediately. */
86#if defined(XTC_INJECT_DISABLE)
87# define XTC_INJECTION_POINT(name) ((void)0)
88#else
89# define XTC_INJECTION_POINT(name) xtc_inject_trigger(name)
90#endif
91
92#endif /* XTC_INJECT_H */