xtc_inspect(3)
---xtc_inspect(3)
live process and loop introspection
| XTC_INSPECT(3) | Library Functions Manual | XTC_INSPECT(3) |
NAME
xtc_inspect_procs,
xtc_inspect_loops,
xtc_proc_info,
xtc_runtime_info — live
process and loop introspection
SYNOPSIS
#include <xtc.h>
#include <xtc_inspect.h>
#include <xtc_runtime.h>
typedef int (*xtc_inspect_proc_fn)(const
xtc_proc_info_t *info, void *user);
typedef int (*xtc_inspect_loop_fn)(const xtc_loop_info_t
*info, void *user);
int
xtc_inspect_procs(xtc_inspect_proc_fn
cb, void
*user);
int
xtc_inspect_loops(xtc_inspect_loop_fn
cb, void
*user);
int
xtc_proc_info(xtc_pid_t
pid, xtc_proc_info_t
*out);
int
xtc_runtime_info(xtc_runtime_info_t
*out);
DESCRIPTION
xtc_inspect is the programmatic form of
the debugger's xtc-procs and
xtc-loops commands (xtc_proc(3),
xtc_loop(3)), callable from inside a running program
rather than from a stopped one. It is the libxtc analog of Erlang's
erlang:process_info()
plus the data
observer
renders: given the live runtime, enumerate every proc and loop and read each
one's vital signs. Its consumers are an admin command (a “SHOW
PROCESSES” verb), a metrics scraper, or a terminal observer.
Each call takes a best-effort snapshot under the per-loop slot locks. For the duration of the call the proc set is consistent: no proc is created or reaped out from under the walk. The per-proc mailbox counters are read under the mailbox lock, so they are individually coherent. The scheduler-owned run state is sampled: it reflects an instant during the call and may change immediately after. A snapshot is therefore a faithful point-in-time view, not a stop-the-world freeze.
The enumeration callbacks run
after all internal
locks are released. A callback may freely call back into the proc and loop
APIs (including
xtc_send(),
xtc_proc_info()), or another
xtc_inspect_procs() without risk of self-deadlock or
lock-order inversion. A callback returns 0 to
continue the walk and any non-zero value to stop early; the enumeration
functions then return the number of items visited so far.
xtc_inspect_procs()
invokes cb once per live proc, across all loops,
passing a pointer to a populated xtc_proc_info_t and
the caller's user pointer. It returns the number of
procs visited, or a negative XTC_E_* code on
error.
xtc_inspect_loops()
invokes cb once per registered loop, passing a
xtc_loop_info_t. It returns the loop count, or a
negative XTC_E_* code.
xtc_proc_info()
snapshots a single proc, named by pid, into
*out. It is the
erlang:process_info() analog for one identity.
A proc snapshot is reported in:
typedef struct xtc_proc_info {
xtc_pid_t pid;
int run_state; /* enum xtc_proc_run_state */
int park_reason; /* enum xtc_proc_park */
int alive;
int kill_pending;
size_t mbox_len; /* current depth */
size_t mbox_peak; /* high-water mark */
size_t mbox_cap;
size_t mbox_saved; /* selective-receive save queue */
uint64_t mbox_recv_total; /* messages ever accepted */
uint64_t mbox_drop_total; /* messages ever rejected */
} xtc_proc_info_t;
The fields are:
- pid
- The proc identity.
- run_state
- The sampled scheduler state, one of the enum xtc_proc_run_state values below.
- park_reason
- Why a
XTC_PROC_PARKEDproc is parked, one of the enum xtc_proc_park values below;XTC_PARK_NONEwhen the proc is not parked. - alive
- Non-zero while the proc is live.
- kill_pending
- Non-zero if an asynchronous
xtc_exit_pid() has been delivered but not yet acted on. - mbox_len
- The live mailbox depth. This is the single most useful health signal in a
message-passing system: a large or growing value is the most common
pathology, the same vital sign the debugger's
xtc-procsranks on. - mbox_peak
- The mailbox high-water mark; a peak far above mbox_len records a burst the proc fell behind on.
- mbox_cap
- The mailbox capacity bound.
- mbox_saved
- The selective-receive save-queue depth (xtc_proc(3)).
- mbox_recv_total
- Lifetime count of messages accepted.
- mbox_drop_total
- Lifetime count of messages rejected because the mailbox was full or the proc was dead.
enum xtc_proc_run_state mirrors the scheduler task state:
XTC_PROC_SCHEDULED- Runnable, waiting for a turn on its loop.
XTC_PROC_RUNNING- Currently executing on its loop's thread.
XTC_PROC_PARKED- Blocked; see park_reason.
XTC_PROC_DONE- Finished, awaiting reap.
enum xtc_proc_park records why a parked proc is waiting:
XTC_PARK_NONE- Not parked.
XTC_PARK_FD- Waiting on a file descriptor
(
xtc_proc_wait_fd()). XTC_PARK_TIMER- Waiting on a timer
(
xtc_proc_sleep()) or a timedxtc_recv(). XTC_PARK_MAILBOX- Waiting for a message (a blocking
xtc_recv()).
A loop snapshot is reported in:
typedef struct xtc_loop_info {
int loop_id; /* 0 standalone, exec slot + 1 otherwise */
int n_procs; /* live procs homed on this loop */
int n_alive; /* live tasks (procs + plain tasks) */
uint64_t tasks_run;
uint64_t steals;
} xtc_loop_info_t;
tasks_run and steals are the scheduler-utilization view: how much work the loop has run and how much it took by work-stealing.
Link and monitor topology is intentionally NOT exposed by the live
API. A proc mutates its own link and monitor lists without a lock, so
walking them from another thread would race. To inspect link/monitor
topology use the debugger (xtc-proc), which runs
against a stopped program; the live API reports only the fields that are
safe to read concurrently -- the mailbox counters, read under the mailbox
lock, and the sampled run state.
RETURN VALUES
xtc_runtime_info() fills
*out with a one-shot snapshot of the running
configuration -- loop count, online / performance / efficiency CPU counts,
NUMA node count, and the configured vs currently-accounted memory -- so a
program need not assemble that itself. It returns
XTC_OK on success.
xtc_inspect_procs() returns the number of
procs visited; xtc_inspect_loops() returns the
number of loops visited. Both return a negative
XTC_E_* code on error.
xtc_proc_info() returns
XTC_OK on success,
XTC_E_NOTFOUND if no live proc has the given
pid, or XTC_E_INVAL if
out is NULL. See
xtc_strerror(3).
EXAMPLES
Rank live procs by mailbox depth, the way a “SHOW PROCESSES” admin command would:
static int
on_proc(const xtc_proc_info_t *p, void *user)
{
(void)user;
if (p->mbox_len > 0)
printf("pid=%llu mbox=%zu peak=%zu state=%d\n",
(unsigned long long)p->pid,
p->mbox_len, p->mbox_peak, p->run_state);
return (0); /* 0 = keep going */
}
int n = xtc_inspect_procs(on_proc, NULL);
printf("%d live procs\n", n);
Snapshot one proc by pid:
xtc_proc_info_t info;
if (xtc_proc_info(pid, &info) == XTC_OK && info.mbox_len > info.mbox_cap / 2)
log_warn("proc %llu mailbox half full", (unsigned long long)pid);
SEE ALSO
AUTHORS
The xtc project.
| June 1, 2026 | Debian |