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 <stdint.h>
23#include <stdatomic.h>
24
25#include "xtc.h"
26
27typedef enum xtc_res_kind {
28 XTC_RES_TASKS = 0, /* live xtc_task_t allocations */
29 XTC_RES_CHANNELS = 1, /* live xtc_chan_* objects */
30 XTC_RES_CHAN_SLOTS = 2, /* in-flight messages across all chans */
31 XTC_RES_FDS = 3, /* open fds attributable to xtc */
32 XTC_RES_MEM_BYTES = 4, /* bytes in xtc-tracked allocations */
33 XTC_RES_INBOX_MSGS = 5, /* cross-loop inbox messages in flight */
34
35 XTC_RES__COUNT
36} xtc_res_kind_t;
37
38/*
39 * Caps. Zero means "no cap" (unbounded; debug only). Defaults
40 * pick reasonable values for a 4-loop M5 executor on a workstation.
41 */
42typedef struct xtc_res_caps {
43 int64_t tasks; /* default 100000 */
44 int64_t channels; /* default 4096 */
45 int64_t chan_slots; /* default 1000000 */
46 int64_t fds; /* default 65536 */
47 int64_t mem_bytes; /* default 1 GiB */
48 int64_t inbox_msgs; /* default 65536 (per loop, not global) */
50
51#define XTC_RES_CAPS_DEFAULT { \
52 .tasks = 100000, \
53 .channels = 4096, \
54 .chan_slots = 1000000, \
55 .fds = 65536, \
56 .mem_bytes = 1024L * 1024 * 1024, \
57 .inbox_msgs = 65536 \
58}
59
60typedef struct xtc_res {
61 xtc_res_caps_t caps;
62 _Atomic int64_t used[XTC_RES__COUNT];
63 _Atomic int64_t high[XTC_RES__COUNT]; /* high-water mark for stats */
64 _Atomic int64_t rejects[XTC_RES__COUNT];/* count of XTC_E_RESOURCE returns */
65
66 /* High-water alert callback: fires once when used / cap crosses
67 * the threshold percent (e.g. 0.8 = 80%). Re-arms when used
68 * drops below the threshold so a second crossing fires again.
69 * Set via xtc_res_set_alert. */
70 double alert_pct[XTC_RES__COUNT];
71 _Atomic int alert_armed[XTC_RES__COUNT]; /* 1 = ready to fire */
72 void (*alert_fn)(xtc_res_kind_t k, int64_t used,
73 int64_t cap, void *user);
74 void *alert_user;
75} xtc_res_t;
76
77/*
78 * PUBLIC: int xtc_res_init __P((xtc_res_t *, const xtc_res_caps_t *));
79 * PUBLIC: int xtc_res_acquire __P((xtc_res_t *, xtc_res_kind_t, int64_t));
80 * PUBLIC: void xtc_res_release __P((xtc_res_t *, xtc_res_kind_t, int64_t));
81 * PUBLIC: int64_t xtc_res_used __P((const xtc_res_t *, xtc_res_kind_t));
82 * PUBLIC: int64_t xtc_res_high __P((const xtc_res_t *, xtc_res_kind_t));
83 * PUBLIC: int64_t xtc_res_rejects __P((const xtc_res_t *, xtc_res_kind_t));
84 * PUBLIC: void xtc_res_set_cap __P((xtc_res_t *, xtc_res_kind_t, int64_t));
85 */
86int xtc_res_init(xtc_res_t *r, const xtc_res_caps_t *caps);
87
88/*
89 * Try to charge `n` units of `kind` to `r`. Returns:
90 * XTC_OK on success
91 * XTC_E_RESOURCE if the request would exceed the cap
92 * XTC_E_INVAL on a bad kind / negative n / NULL r
93 *
94 * Atomic and lock-free.
95 */
96int xtc_res_acquire(xtc_res_t *r, xtc_res_kind_t k, int64_t n);
97
98/*
99 * Release `n` units. Never fails; clamps at zero on underflow
100 * (treated as a programming error in debug builds).
101 */
102void xtc_res_release(xtc_res_t *r, xtc_res_kind_t k, int64_t n);
103
104int64_t xtc_res_used(const xtc_res_t *r, xtc_res_kind_t k);
105int64_t xtc_res_high(const xtc_res_t *r, xtc_res_kind_t k);
106int64_t xtc_res_rejects(const xtc_res_t *r, xtc_res_kind_t k);
107void xtc_res_set_cap(xtc_res_t *r, xtc_res_kind_t k, int64_t cap);
108
109/* Configure a high-water alert. Fires `fn(kind, used, cap, user)`
110 * once when `used >= pct * cap` for the named resource; re-arms
111 * when used drops below. pct in (0.0, 1.0). Pass fn=NULL to
112 * disable. Per-resource: alerts are independent.
113 *
114 * PUBLIC: int xtc_res_set_alert __P((xtc_res_t *, xtc_res_kind_t, double));
115 * PUBLIC: int xtc_res_set_alert_fn __P((xtc_res_t *, void (*)(xtc_res_kind_t, int64_t, int64_t, void *), void *));
116 */
117int xtc_res_set_alert(xtc_res_t *r, xtc_res_kind_t k, double pct);
118int xtc_res_set_alert_fn(xtc_res_t *r,
119 void (*fn)(xtc_res_kind_t, int64_t, int64_t, void *),
120 void *user);
121
122#endif /* XTC_RES_H */