pub type PollFn = unsafe extern "C-unwind" fn(state: *mut u8, task_ctx: *mut u8) -> i64;Expand description
The signature every compiled async fn’s poll function has – both the
hand-written ones this module’s tests drive it with, and the ones
async_lower.rs (Task 5) generates. Reads and writes state’s slots (see
STATE_SLOT_TAG and friends) and reports POLL_PENDING or
POLL_READY.
task_ctx is unused in this phase, and every call site in this module
passes null. The parameter exists now, rather than being added later,
because a future phase (channels, timers) needs a task to be able to park
against an external event instead of being busy-repolled, and adding a
parameter afterward would mean changing every already-compiled poll
function’s signature.
"C-unwind", not plain "C": a panic cannot cross a plain "C"
function’s boundary at all – it aborts the whole process on the spot,
regardless of the workspace’s unwind panic strategy. Some of this module’s
diagnostics are panics that a caller is meant to be able to observe –
nova_rt_task_take_output’s take-once check, and [poll_one]’s
rejection of a poll status the ABI does not define – and each has to leave
the #[no_mangle] entry point it starts under. Declaring the ABI
"C-unwind" permits that, and every entry point here (this indirect call
included) shares it so this module has one ABI rather than two. It changes
nothing else: "C-unwind" was stabilized in Rust 1.71 (under this
workspace’s 1.78 MSRV) and marshals parameters and return values
identically to "C", so a generated call site is byte-identical either way.
Constraint on generated poll functions: a panic must not cross their
boundary. "C-unwind" says an unwind may pass through without
aborting; it does not make a frame able to survive one. A poll function
emitted by Cranelift or LLVM has no landing pads and no drop glue, so an
unwind through it would skip whatever cleanup its frame ought to do and
leave the executor’s QUEUE/TASKS describing a task that is neither
running nor finished. Anything in a generated poll function that could
panic must therefore either be provably unable to (nova_rt_check_bounds
and nova_rt_panic_str both abort, not unwind) or catch it before
returning. Every diagnostic in this module that a well-formed compiled
Nova program can reach therefore goes through [abort_with] instead of
panicking; the panics named above are reachable only from a Rust caller or
from a compiler bug (see each one’s own doc comment). The
permission this ABI grants exists for the Rust-side entry points below, not
for compiled Nova frames.