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