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
+44
View File
@@ -0,0 +1,44 @@
#ifndef VMSIG_ADAPTER_UTIL_H
#define VMSIG_ADAPTER_UTIL_H
#include <stddef.h>
/* adapter_util.h — shared primitive "blocking API -> completion eventfd".
*
* A bridge turning a synchronous CPU-bound / blocking neighbor call (vmie,
* vmctl) into a readiness source for the epoll core: the loop thread posts a request, a
* separate worker thread runs the blocking work and signals a completion eventfd; on it
* the loop wakes and collects the result in on_readiness. Reused by the memctx
* (off-loop bootstrap) and input adapters. */
typedef struct vmsig_worker vmsig_worker;
#define VMSIG_WORK_SLOT 256 /* req/res slot size (POD, copied) */
/* Callback run IN the worker thread: req -> res (both POD <= VMSIG_WORK_SLOT).
* Returns 0/-1 (the code is stored alongside, see vmsig_worker_poll). Must not touch
* core structures — only compute res from req. */
typedef int (*vmsig_work_fn)(void* user, const void* req, void* res);
/* Create a worker pool of nthreads threads over a shared queue (nthreads>=1). vmie
* allows parallel read-only readers; for a serial channel (QMP) use 1. max_depth — the
* request-queue depth ceiling (<=0 => default): submit beyond it is rejected (-1) so an
* untrusted flood does not grow into OOM. NULL on error. */
vmsig_worker* vmsig_worker_new(vmsig_work_fn fn, void* user, int nthreads, int max_depth);
/* Stop the threads (join) and free. Safe on NULL. */
void vmsig_worker_free(vmsig_worker* w);
/* completion eventfd: the adapter registers it as a VMSIG_RDY_EVENTFD source. */
int vmsig_worker_evfd(const vmsig_worker* w);
/* loop thread: post a request (copied, len <= VMSIG_WORK_SLOT). 0/-1. */
int vmsig_worker_submit(vmsig_worker* w, const void* req, size_t len);
/* loop thread (in on_readiness): drain the completion eventfd. */
void vmsig_worker_ack(vmsig_worker* w);
/* loop thread: collect a ready result. 1 — written to res (+ *rc = fn code),
* 0 — empty, -1 — error. Drain in a loop until 0. */
int vmsig_worker_poll(vmsig_worker* w, void* res, size_t cap, int* rc);
#endif /* VMSIG_ADAPTER_UTIL_H */