#ifndef VMSIG_ADAPTER_UTIL_H #define VMSIG_ADAPTER_UTIL_H #include /* 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 */