xtc_trace(3)
---xtc_trace(3)
causal message tracing (libxtc’s seq_trace)
| XTC_TRACE(3) | Library Functions Manual | XTC_TRACE(3) |
NAME
xtc_trace_enable,
xtc_trace_reset,
xtc_trace_dump, xtc_hlc_now
— causal message tracing (libxtc's
seq_trace)
LIBRARY
libxtc
SYNOPSIS
#include <xtc.h>
#include <xtc_trace.h>
typedef int (*xtc_trace_fn)(const xtc_trace_rec_t *rec, void *user);
int
xtc_trace_enable(int
on);
int
xtc_trace_reset(void);
int
xtc_trace_dump(xtc_trace_fn
cb, void
*user);
uint64_t
xtc_hlc_now(void);
DESCRIPTION
xtc_trace is libxtc's
seq_trace:
a bounded, opt-in ring of message-passing events -- each send and receive
between procs -- stamped so that the causal order of one request can be
reconstructed across procs and cores even when the wall-clock order in which
the records arrived lies. It is the analog of Erlang's trace token that
rides along message sends, letting you answer “who sent this, and
what caused that” in a system where the answer is spread across many
mailboxes.
Every traced event is stamped with a hybrid logical clock (HLC): a 64-bit value whose high 48 bits are a monotonic physical-time component (microseconds) and whose low 16 bits are a logical counter. A single global clock ticks once per traced event, so a send's stamp is always strictly less than the stamp of the receive it causes. Sorting the records by HLC therefore yields a true happens-before order, not a thread-local arrival order: when two cores disagree about which message landed first, the HLC is the truth.
The causal edge is made explicit, not merely implied by ordering:
a XTC_TRACE_RECV record carries the originating
send's HLC stamp in its cause field. Following
cause from a receive back to the matching send, and
from that send's proc to the receive that triggered it, walks the chain of
one request as it fans out across procs.
Tracing is OFF by default. When disabled it costs a single relaxed atomic load on the message hot path, so a production build that never enables it pays essentially nothing. When enabled it serializes ring writes under a lock and overwrites the oldest records once the ring is full. Enable it to debug a specific problem -- as you would reach for recon or dbg on the BEAM -- not as an always-on production tax.
xtc_trace_enable()
turns tracing on when on is non-zero and off when it
is zero. It returns the previous state (non-zero if tracing was on), so a
caller can save and restore it.
xtc_trace_reset()
drops all buffered trace records, leaving the enable state unchanged. It
returns XTC_OK. Call it before a workload to ensure
the ring holds only the events of interest.
xtc_trace_dump()
visits the buffered records in causal (HLC-ascending) order, invoking
cb once per record with a pointer to the record and
the caller's user pointer. The callback returns
0 to continue or any non-zero value to stop the walk
early. The callbacks run
after
the internal trace lock is released, so a callback may freely call back into
libxtc -- including
xtc_send(),
the inspection API, or xtc_trace_dump() itself --
without risk of self-deadlock. It returns the number of records visited, or
a negative XTC_E_* code on error.
xtc_hlc_now()
returns the current value of the global HLC. It is intended for tests and
for display; an application does not normally need it, since the stamps
already ride in the trace records.
A trace record is reported in:
typedef struct xtc_trace_rec {
uint64_t hlc; /* this event's HLC stamp */
uint64_t cause; /* RECV: the originating send's HLC; else 0 */
int kind; /* enum xtc_trace_kind */
xtc_pid_t self; /* the proc the event happened in */
xtc_pid_t peer; /* the other proc (dest / source / child) */
uint32_t detail; /* SEND/RECV: payload bytes; EXIT: reason */
} xtc_trace_rec_t;
The fields are:
- hlc
- This event's HLC stamp. Records sort by this value into causal order.
- cause
- For a
XTC_TRACE_RECVrecord, the HLC stamp of the send that produced the received message;0for every other kind. This is the explicit causal edge. - kind
- One of the enum xtc_trace_kind values below.
- self
- The proc in which the event happened: the sender for a send, the receiver for a receive, the parent for a spawn, the exiting proc for an exit.
- peer
- The other proc involved: the destination of a send, the source of a receive, or the spawned child.
- detail
- For a send or receive, the message payload size in bytes; for an exit, the exit reason.
enum xtc_trace_kind names the event kinds:
XTC_TRACE_SEND- self sent a message to peer.
XTC_TRACE_RECV- self received a message from peer; cause holds the originating send's stamp.
XTC_TRACE_SPAWN- self (the parent) spawned peer (the child).
XTC_TRACE_EXIT- self exited; detail holds the exit reason.
The visit callback has the type
typedef int (*xtc_trace_fn)(const xtc_trace_rec_t *rec, void *user);
where rec points at
one record (valid only for the duration of the call) and
user is the pointer passed to
xtc_trace_dump().
The per-shard HLC used by the MVCC data path is a separate, later use of the same clock idea; it is not the global trace clock described here.
RETURN VALUES
xtc_trace_enable() returns the previous
enable state: non-zero if tracing was already on, 0
if it was off.
xtc_trace_reset() returns
XTC_OK.
xtc_trace_dump() returns the number of
records visited, or a negative XTC_E_* code on
error. See xtc_strerror(3).
xtc_hlc_now() returns the current global
HLC value.
EXAMPLES
Enable tracing, run a workload, and print the records in causal order:
static int
on_rec(const xtc_trace_rec_t *r, void *user)
{
(void)user;
printf("HLC=%llu kind=%d self=%llu peer=%llu cause=%llu det=%u\n",
(unsigned long long)r->hlc, r->kind,
(unsigned long long)r->self,
(unsigned long long)r->peer,
(unsigned long long)r->cause, r->detail);
return (0); /* 0 = keep going */
}
int was_on = xtc_trace_enable(1); /* opt in */
xtc_trace_reset(); /* start from a clean ring */
run_workload(); /* exercise the procs in question */
int n = xtc_trace_dump(on_rec, NULL);
printf("%d trace records\n", n);
if (!was_on)
xtc_trace_enable(0); /* stop paying for it */
Reading the dump, a XTC_TRACE_RECV whose
cause equals the hlc of an
earlier XTC_TRACE_SEND is the same message; chaining
those edges reconstructs a request's path across procs.
SEE ALSO
AUTHORS
The xtc project.
| June 1, 2026 | Debian |