libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_res.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_res.h
6 * Resource governance. An xtc_res_t is a per-executor (or
7 * per-loop) accountant that tracks bounded resources: tasks,
8 * channels, channel slots, file descriptors, memory. Acquire is
9 * atomic and either succeeds (counter <= cap) or returns
10 * XTC_E_RESOURCE; release is unconditional.
11 *
12 * The point of this subsystem is the BEAM/Seastar/libumem
13 * "predictably reliable" promise: a misbehaving client cannot
14 * exhaust the host because every resource has a documented cap,
15 * a documented behaviour at the cap, and a way for the operator
16 * to observe both.
17 */
18
19#ifndef XTC_RES_H
20#define XTC_RES_H
21
22#include "xtc_export.h"
23
24#include <stdint.h>
25#include <stdatomic.h>
26
27#include "xtc.h"
28
29typedef enum xtc_res_kind {
30 XTC_RES_TASKS = 0, /* live xtc_task_t allocations */
31 XTC_RES_CHANNELS = 1, /* live xtc_chan_* objects */
32 XTC_RES_CHAN_SLOTS = 2, /* in-flight messages across all chans */
33 XTC_RES_FDS = 3, /* open fds attributable to xtc */
34 XTC_RES_MEM_BYTES = 4, /* bytes in xtc-tracked allocations */
35 XTC_RES_INBOX_MSGS = 5, /* cross-loop inbox messages in flight */
36
37 XTC_RES__COUNT
38} xtc_res_kind_t;
39
40/*
41 * Caps. Zero means "no cap" (unbounded; debug only). Defaults
42 * pick reasonable values for a 4-loop M5 executor on a workstation.
43 */
44typedef struct xtc_res_caps {
45 int64_t tasks; /* default 100000 */
46 int64_t channels; /* default 4096 */
47 int64_t chan_slots; /* default 1000000 */
48 int64_t fds; /* default 65536 */
49 int64_t mem_bytes; /* default 1 GiB */
50 int64_t inbox_msgs; /* default 65536 (per loop, not global) */
52
53#define XTC_RES_CAPS_DEFAULT { \
54 .tasks = 100000, \
55 .channels = 4096, \
56 .chan_slots = 1000000, \
57 .fds = 65536, \
58 .mem_bytes = 1024L * 1024 * 1024, \
59 .inbox_msgs = 65536 \
60}
61
62typedef struct xtc_res {
63 xtc_res_caps_t caps;
64 _Atomic int64_t used[XTC_RES__COUNT];
65 _Atomic int64_t high[XTC_RES__COUNT]; /* high-water mark for stats */
66 _Atomic int64_t rejects[XTC_RES__COUNT];/* count of XTC_E_RESOURCE returns */
67
68 /* High-water alert callback: fires once when used / cap crosses
69 * the threshold percent (e.g. 0.8 = 80%). Re-arms when used
70 * drops below the threshold so a second crossing fires again.
71 * Set via xtc_res_set_alert. */
72 double alert_pct[XTC_RES__COUNT];
73 _Atomic int alert_armed[XTC_RES__COUNT]; /* 1 = ready to fire */
74 void (*alert_fn)(xtc_res_kind_t k, int64_t used,
75 int64_t cap, void *user);
76 void *alert_user;
77} xtc_res_t;
78
79/*
80 * PUBLIC: int xtc_res_init __P((xtc_res_t *, const xtc_res_caps_t *));
81 * PUBLIC: int xtc_res_acquire __P((xtc_res_t *, xtc_res_kind_t, int64_t));
82 * PUBLIC: void xtc_res_release __P((xtc_res_t *, xtc_res_kind_t, int64_t));
83 * PUBLIC: int64_t xtc_res_used __P((const xtc_res_t *, xtc_res_kind_t));
84 * PUBLIC: int64_t xtc_res_high __P((const xtc_res_t *, xtc_res_kind_t));
85 * PUBLIC: int64_t xtc_res_rejects __P((const xtc_res_t *, xtc_res_kind_t));
86 * PUBLIC: void xtc_res_set_cap __P((xtc_res_t *, xtc_res_kind_t, int64_t));
87 */
88XTC_API int xtc_res_init(xtc_res_t *r, const xtc_res_caps_t *caps);
89
90/*
91 * Try to charge `n` units of `kind` to `r`. Returns:
92 * XTC_OK on success
93 * XTC_E_RESOURCE if the request would exceed the cap
94 * XTC_E_INVAL on a bad kind / negative n / NULL r
95 *
96 * Atomic and lock-free.
97 */
98XTC_API int xtc_res_acquire(xtc_res_t *r, xtc_res_kind_t k, int64_t n);
99
100/*
101 * Release `n` units. Never fails; clamps at zero on underflow
102 * (treated as a programming error in debug builds).
103 */
104XTC_API void xtc_res_release(xtc_res_t *r, xtc_res_kind_t k, int64_t n);
105
106XTC_API int64_t xtc_res_used(const xtc_res_t *r, xtc_res_kind_t k);
107XTC_API int64_t xtc_res_high(const xtc_res_t *r, xtc_res_kind_t k);
108XTC_API int64_t xtc_res_rejects(const xtc_res_t *r, xtc_res_kind_t k);
109XTC_API void xtc_res_set_cap(xtc_res_t *r, xtc_res_kind_t k, int64_t cap);
110
111/* Configure a high-water alert. Fires `fn(kind, used, cap, user)`
112 * once when `used >= pct * cap` for the named resource; re-arms
113 * when used drops below. pct in (0.0, 1.0). Pass fn=NULL to
114 * disable. Per-resource: alerts are independent.
115 *
116 * PUBLIC: int xtc_res_set_alert __P((xtc_res_t *, xtc_res_kind_t, double));
117 * PUBLIC: int xtc_res_set_alert_fn __P((xtc_res_t *, void (*)(xtc_res_kind_t, int64_t, int64_t, void *), void *));
118 */
119XTC_API int xtc_res_set_alert(xtc_res_t *r, xtc_res_kind_t k, double pct);
120XTC_API int xtc_res_set_alert_fn(xtc_res_t *r,
121 void (*fn)(xtc_res_kind_t, int64_t, int64_t, void *),
122 void *user);
123
124#endif /* XTC_RES_H */