8.3 Consuming events
A consumed event is described by struct peios_event. The kernel-stamped header is copied to you by value; the two variable parts point into the ring mapping.
;
The trusted metadata is the point of KMES: the timestamp, the identity GUIDs (the effective and true tokens, and the process), and the origin_class are stamped by the kernel and cannot be forged by the emitter. sequence is per-CPU, per-boot monotonic — a gap in it means events were lost (overwritten before you drained them).
Lifetime:
event_typeandpayloadpoint into the ring mapping and are valid only until the next read advance, and only while the slot has not been overwritten. Copy out whatever you need before continuing to the next event.
8.3.0.1 Attaching to a ring #
int ;
The low-level primitive: attach to CPU cpu_id's ring buffer, returning a fd and writing the data-region capacity to *capacity_out. Discover the CPU count by counting up from 0 until peios_event_attach returns -1 with errno == EINVAL. Requires SeSecurityPrivilege (EPERM otherwise). You then mmap the fd via peios_event_ring_map. Most callers should use the high-level reader instead, which does the attach and mmap for you.
8.3.0.2 The high-level reader #
typedef struct peios_event_reader peios_event_reader;
peios_event_reader *;
void ;
int ;
int ;
uint64_t ;
The reader owns the attach + mmap and hides the whole lock-free drain — memory barriers, lapping recovery, sequence-gap (lost-event) accounting, buffer resize/generation handling, and the futex wait. You just loop next/wait.
peios_event_reader_openattaches tocpu_idand maps its ring, ready to drain (NULLwitherrnoon failure).peios_event_reader_closetears it down.peios_event_reader_nextfetches the next event intoout(non-NULL). Returns1(event filled),0(none available right now — considerwait), or-1witherrno. Theoutpointers are valid only until the next call.peios_event_reader_waitblocks until events are available ortimeout_mselapses (negative = forever). Returns1(callnext),0(timeout/interrupted), or-1.peios_event_reader_lostreturns the cumulative count of lost events (from sequence gaps) — poll it to monitor whether you're draining fast enough.
The canonical consume loop, per CPU:
peios_event_reader *r = ;
for
;
To consume the whole machine, run one reader per CPU (discover the count as above), each typically on its own thread.
8.3.0.3 The low-level ring #
For callers that want to drive the drain themselves — integrating the rings into a custom event loop, say — the ring API exposes the mapping directly. The accessors apply the correct memory barriers; you own the read position and the empty/lapping/generation checks.
; /* opaque */
int ;
void ;
uint64_t ;
uint64_t ; /* acquire */
uint64_t ; /* acquire */
uint64_t ;
void ;
ssize_t ;
int ;
peios_event_ring_mapmaps and validates a ring fd frompeios_event_attach;ringmust be zeroed or previously unmapped (remapping an active ring failsEBUSY).peios_event_ring_unmapreleases it.- Positions are free-running byte counters.
write_posis where the producer will write next (acquire-loaded);tail_posis the oldest still-live byte (advances as the ring laps); an event lives at(read_pos & (capacity - 1)). You drain by walkingread_posfromtail_postowardwrite_pos.generationchanges when the buffer is resized — re-readcapacitywhen it does. peios_event_ring_event_atparses the event atread_posintooutand returns its byte size (advanceread_posby that), or-1if the slot is corrupt. You must have confirmedread_posis in[tail_pos, write_pos)first. Passout == NULLto validate a slot and get its size without borrowing theevent_type/payloadpointers.- Before sleeping, arm the advisory wake flag with
peios_event_ring_set_need_wake(ring, 1), thenpeios_event_ring_waitfutex-waits until events pastread_posmay be available ortimeout_mselapses (negative = forever):1(drain now),0(timeout/interrupted),-1.
The low-level loop mirrors the high-level one but with the position bookkeeping in your hands:
uint64_t rp = ;
for
Reach for this only when the high-level reader's loop doesn't fit your event model; for almost everything, peios_event_reader_* is the right tool.