vmsig: a neutral signaling layer between sensors/input and controls

An epoll-driven, neutral transfer-event bus that connects sensors and input
actuators to one or more controls, bidirectionally. It owns the transfer context
and events — delivery order, priority, protocol-level timing, and an
interrupt-driven event model over fd sources (eventfd/timerfd/sockets) — and
stays agnostic to both the sensor/input drivers and the control.

What lives here:
- memctx: a coherent address-space context per endpoint — the guest address-space
  root paired with a pre-opened read-only RAM-region fd, with per-endpoint epoch
  invalidation and retained replay to late subscribers. Perception lives in
  out-of-tree sensor libraries that consume this datum read-only.
- exclusive-ownership leases for destructive resource classes (input, power,
  memory-write).
- write-signaled memory writes (MEMWRITE): an atomic write to guest memory routed
  through the seam under an exclusive lease, never a writable mapping.
- a host-management seam for VM lifecycle/status and a neutral input-injection
  command path.
- multi-VM endpoints; capability-gated, audited control authorization over an
  in-process or unix-socket transport.

Builds against headers only by default (a stub mode that exercises the seam
without a VM); armed builds link the real sensor/input libraries behind flags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-20 18:46:31 +03:00
commit 709f4b586a
36 changed files with 5820 additions and 0 deletions
+170
View File
@@ -0,0 +1,170 @@
#ifndef VMSIG_CORE_INTERNAL_H
#define VMSIG_CORE_INTERNAL_H
#include "vmsig_core.h"
#include <signal.h>
/* Private internals of the epoll core. Each registered fd carries a
* core_slot* in epoll_event.data.ptr; the slot's role decides how to handle it. */
#define VMSIG_MAX_EVENTS 64
#define VMSIG_MAX_ADAPTERS 256 /* up to ~64 VMs * 3 adapters + slack (mode A) */
#define VMSIG_MAX_CONTROLS 64 /* concurrent pollers; more => processes (C) */
#define VMSIG_ADAPTER_FDS 8 /* max fds per adapter */
#define VMSIG_DOWN_PENDING_MAX 256 /* ceiling of DOWN commands per poller in ctx (fairness) */
typedef enum {
SLOT_WAKEUP, /* wake/stop eventfd */
SLOT_ADAPTER, /* adapter fd (timerfd/eventfd/socket) */
SLOT_CTX_TIMING, /* context pacing timerfd */
SLOT_CONTROL, /* out-of-process control socket */
SLOT_SOURCE, /* arbitrary fd + callback (e.g. listen-fd) */
SLOT_DEAD /* detached (reaped); loop ignores it */
} slot_role;
typedef struct core_slot {
slot_role role;
int fd;
/* for SLOT_ADAPTER */
const vmsig_adapter_ops* ops;
vmsig_adapter* adapter;
uint32_t cookie;
/* for SLOT_CONTROL */
const vmsig_control_ops* cops;
void* ctl;
/* for SLOT_SOURCE */
void (*on_source)(void* user, uint32_t events);
void (*on_free)(void* user); /* invoked at core_free (source cleanup) */
void* source_user;
} core_slot;
typedef struct {
const vmsig_adapter_ops* ops;
vmsig_adapter* a;
uint32_t endpoint;
} core_adapter_ent;
/* ===== Retained address-space context (MEMCTX seam) =====
* The core retains per-endpoint "a current context exists in the current epoch" + the
* adapter's reg pointer (describe/share_fd/invalidate). Replays to a late qualified
* subscriber (CAP_MEMCTX + source_mask + endpoint) re-sharing the RO-fd. Does NOT store a
* copy of the locator: on delivery/replay it calls reg.describe (adapter snapshot) +
* reg.share_fd (fresh RO-fd). Invalidated on epoch change; cleared on unregister/free. */
typedef struct {
int registered; /* adapter called register_memctx (reg valid) */
int valid; /* a published context exists in the current epoch */
uint32_t epoch; /* snapshot epoch (== core epoch[ep] when valid) */
vmsig_memctx_reg reg; /* valid when registered */
} core_memctx_cell;
/* ===== Lease layer (arbitration of exclusive ownership of destructive resources) =====
* One cell per (endpoint, lease-class): who owns it (origin) + a snapshot of arb_prio at
* acquisition time. owner=0 => free. The snapshot (rather than the live grant) makes the
* policy resilient to the owner's grant changing after acquisition. */
#define VMSIG_LEASE_CLASSES 3 /* INPUT, POWER, MEMWRITE (== VMSIG_LEASE_CLASS_MAX) */
typedef struct {
uint32_t owner; /* origin (gen<<16)|(id+1) of the owner; 0 = free */
uint32_t owner_prio; /* owner's arb_prio at acquisition time (snapshot) */
} core_lease_cell;
struct vmsig_core; /* fwd for core_down_ctx */
/* DOWN emission context: handed to a control in set_emit_down so emit_down knows WHICH
* control issued the command (for grant lookup and enforcement). Stable: lives in the
* fixed controls[] array. */
typedef struct {
struct vmsig_core* core;
int ctl_id;
} core_down_ctx;
typedef struct {
const vmsig_control_ops* ops;
void* ctl;
vmsig_sub sub;
vmsig_grant grant; /* poller's rights ceiling (default-deny) */
core_down_ctx dctx; /* token for emit_down */
int active; /* 0 = detached/reaped (slot free) */
int reap; /* reap requested (deferred) */
core_slot* slot; /* SLOT_CONTROL fd slot (or NULL) */
uint32_t pending; /* DOWN commands of this poller in ctx (fairness cap) */
uint16_t gen; /* slot generation: +1 on each (re)use */
} core_control_ent;
struct vmsig_core {
int epfd;
int wake_fd; /* eventfd: nudge + stop */
vmsig_ctx* ctx;
volatile sig_atomic_t stopping;
core_adapter_ent adapters[VMSIG_MAX_ADAPTERS];
int nadapters;
core_control_ent controls[VMSIG_MAX_CONTROLS];
int ncontrols;
core_slot** slots; /* all allocated slots (for free) */
int nslots;
int cap_slots;
uint32_t epoch[64]; /* per-endpoint VM session epoch */
core_memctx_cell memctx[64]; /* per-endpoint retained context */
core_lease_cell lease[64][VMSIG_LEASE_CLASSES]; /* lease per (endpoint, class) */
vmsig_arb_policy arb_cb; /* preemption policy (NULL=default) */
void* arb_ud;
void (*audit_cb)(void* ud, const vmsig_audit* a);
void* audit_ud;
};
/* Emit an audit record (no-op if no callback is set). Defined in core.c. */
void core_audit(vmsig_core* c, const vmsig_audit* a);
/* Register an fd in epoll + create a slot (see core.c). */
core_slot* core_register_fd(vmsig_core* c, int fd, uint32_t epoll_events, slot_role role);
/* Register an arbitrary fd source with a callback (e.g. a socket listen-fd).
* The callback is called on the loop thread when the fd is ready. on_free (may be NULL)
* is called at vmsig_core_free to clean up the source's resource. 0/-1. */
int core_add_source(vmsig_core* c, int fd, void (*cb)(void* user, uint32_t events),
void* user, void (*on_free)(void* user));
/* Request detaching a control by id (deferred reap after the batch: epoll DEL,
* close fd, ops->close). Safe to call from the control's own on_readable. */
void core_request_drop(vmsig_core* c, int ctl_id);
/* emit hooks handed to adapters (UP) and controls (DOWN). Defined in loop.c. */
int core_emit_up (void* token, vmsig_event* ev);
int core_emit_down(void* token, vmsig_event* ev);
/* ===== Address-space context (MEMCTX seam; retained context) ===== */
/* Context registration hooks (handed to the adapter in vmsig_emit; defined in core.c). */
int core_register_memctx (void* token, const vmsig_memctx_reg* reg);
void core_unregister_memctx(void* token, uint32_t endpoint);
/* Multicast MEMCTX to qualified subscribers + mark the retain cell valid
* (from pump_up on the VMSIG_EV_MEMCTX trigger; defined in loop.c). */
void core_memctx_route(vmsig_core* c, const vmsig_event* trigger);
/* Replay retained MEMCTX to a single (late) subscriber (from vmsig_core_add_control;
* defined in loop.c). */
void core_memctx_replay(vmsig_core* c, int ctl_id);
/* Bump the endpoint's epoch on a destructive lifecycle transition: epoch++, invalidate
* the retain cell, emit MEMCTX_INVALIDATED, request re-bootstrap from the adapter.
* Observed by the core in pump_up on UP VM_LIFECYCLE (defined in loop.c). */
void core_epoch_bump(vmsig_core* c, uint32_t endpoint);
/* ===== Lease layer (defined in loop.c) ===== */
/* Intercept CMD_ACQUIRE/RELEASE/LEASE_STATUS (synchronously from core_emit_down, not in ctx). */
void core_lease_acquire(vmsig_core* c, int ctl_id, const vmsig_event* ev);
void core_lease_release(vmsig_core* c, int ctl_id, const vmsig_event* ev);
void core_lease_status (vmsig_core* c, int ctl_id, const vmsig_event* ev);
/* Reclaim the lease of a dead control (from core_reap, BEFORE e->active=0). */
void core_lease_reap_control(vmsig_core* c, int ctl_id);
/* Wake the loop (eventfd nudge). Defined in loop.c. */
void core_wake(vmsig_core* c);
#endif /* VMSIG_CORE_INTERNAL_H */