diff --git a/library/kernel/service.zig b/library/kernel/service.zig index 881e896..352c907 100644 --- a/library/kernel/service.zig +++ b/library/kernel/service.zig @@ -67,6 +67,15 @@ pub const Callbacks = struct { /// A notification that is not a signal — a subscribed exit event, a bound /// IRQ, a timer landing. The raw badge; decode with the ipc helpers. on_notification: ?*const fn (badge: u64) void = null, + /// A buffered async message (`Received.isMessage`): a pushed event from a + /// provider this service subscribed to, its payload in the receive buffer. + /// Unlike `on_message`, it never goes through the protocol dispatch — so an + /// event whose reserved op number collides with one of this service's own + /// verbs (a `block` `medium_changed` reaching the volume manager, whose own + /// protocol numbers `hello` the same) is decoded by hand here, not + /// mis-dispatched. Default null: the badge alone still reaches + /// `on_notification`, exactly as before this callback existed. + on_buffered_message: ?*const fn (message: []const u8) void = null, /// The reload signal. Default: ignored. on_reload: ?*const fn () void = null, /// The terminate signal, called before the loop returns. The clean exit is @@ -372,6 +381,13 @@ pub fn run(comptime maximum_message: usize, callbacks: Callbacks) void { if (got.isChildExit()) { if (callbacks.subscribers) |subscribers| subscribers.forget(got.childProcessId()); } + // A buffered async message (a pushed event) carries a payload; hand it + // to the service that asked for it. The badge still reaches + // on_notification below, so a coalesced timer/exit riding the same wake + // is not lost — and a service without this callback is unchanged. + if (got.isMessage()) { + if (callbacks.on_buffered_message) |onBuffered| onBuffered(receive[0..got.len]); + } if (callbacks.on_notification) |onNotification| onNotification(got.badge); continue; }