Registering a source
Every source starts by registering. You tell the kernel which hives your process backs, and it hands you a source fd to serve on. The full detail is in rsi/source.h; this guide walks the decisions.
Declare your hives #
A hive is a registry subtree with its own root key. Fill in one struct rsi_hive per hive your source backs:
struct rsi_hive hive = ;
The two decisions per hive:
- Global or private? A global hive (
flags = 0,scope_guidzero) is visible system-wide. A private hive (flags = RSI_HIVE_PRIVATE,scope_guidnon-zero) is scoped — only tokens carrying that scope GUID in their LCS credentials can resolve it. Use a private hive for per-application or per-tenant state that shouldn't be system-visible. - The root GUID. Every hive is anchored at a root key identified by
root_guid. This is the GUID paths in the hive resolve from, and it must match the root your storage actually holds.
Register #
Hand the kernel your hive array and the highest sequence number you've already persisted:
int src = ;
if
/* `src` is the source fd — serve the RSI protocol on it. */
Two things to get right:
SeTcbPrivilegeis required. Registration is a trusted operation; without the privilege you getEPERM. Sources run as trusted system components.max_sequenceis your durability contract. It is the highest sequence number this source has already persisted. The kernel resumes its global sequence counter past it, so it never hands out a number you've used. A brand-new source with no stored state passes0; a source restarting with durable data must scan that data for the highest sequence it ever wrote and pass that. Getting this wrong risks sequence reuse, so make it the first thing your restart path computes.
You can register several hives in one call by passing an array and a count greater than one; the kernel enforces its configured MaxHivesPerSource limit (ENOSPC if you exceed it).
Optional transaction lifetime control #
The kernel also supports lifetime extension version 1. A source using it opens
/dev/pkm_registry, calls REG_SRC_NEGOTIATE with version 1 and zero flags,
retains the returned session identifier, and then calls REG_SRC_REGISTER.
The current rsi_register convenience function uses the legacy registration
sequence; negotiate through the explicit device/ioctl sequence when adopting
this extension.
After reading each request, query REG_SRC_REQUEST_CONTEXT with its request id
and the negotiated session. It returns the original request deadline and any
transaction lifetime and cleanup-lease deadlines, all in CLOCK_MONOTONIC
nanoseconds. Renew live transactions using REG_SRC_RENEW, independently of the
normal request queue. Renewal cannot extend the transaction lifetime or revive
an expired lease. Both read-write transactions and read-only snapshots use the
same ownership rules. Serialize expiry cleanup with transaction operations and
wait for an admitted commit's actual result before reclaiming its state.
The data-frame layout is unchanged. Sources without negotiation retain the legacy protocol. Current loregd requires the extension and must be deployed with a kernel that implements it. The PKM TRM, §5.8.3, specifies the control ioctls and their error and lifetime rules.
After registration #
The returned fd is your serve endpoint — you read(2) requests and write(2) responses on it directly (via the request and response helpers). Closing it deregisters the source and signals EOF to the kernel. Keep it open for the life of the source, and move on to the serve loop.
Next #
- Serving requests — the loop that runs on the source fd.
rsi/source.hreference — every field and error.