Skip to content

wasi-shims: the parking kernel — real pollables, poll, timers, always on (A5) - #71

Merged
lann merged 1 commit into
mainfrom
wasi-blocking-kernel
Aug 10, 2026
Merged

wasi-shims: the parking kernel — real pollables, poll, timers, always on (A5)#71
lann merged 1 commit into
mainfrom
wasi-blocking-kernel

Conversation

@lann

@lann lann commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Track 2, scoped per operator direction to what the known consumer needs (polymorph-iroh's upstream-iroh class: iroh/tokio parking its reactor in wasi:io/poll).

Ships: publicly-constructible Pollable(ready, wait) (the interop seam for consumer-side sockets glue; promise-swap wake contract), @suspending block() and poll() with sync fast paths (per-declaration granularity — the A1 design payoff vs jco's transpile-time flag), real Pollable.timer behind monotonic-clock subscribe-* (the always-ready timer stub was the livelock half), empty-list trap per io.wit. Streams stay buffer-backed (known consumers do no stream I/O).

Always on, not opt-in (operator ruling): chooseMode already degrades to plain on non-JSPI engines — old-stub behavior until a guest genuinely parks, then a clean NeedsJspi instead of a livelock; jspi: false is the per-instantiation opt-out. Contract A5 retires the three-tier framing and the 'never (c) in this package' mission line; intrinsics.md records the narrowed zero-cost pin (sync-only AND no marked providers).

Pins: kernel unit suite + a hand-written genuinely-blocking guest (blocking-guest.wat, cross-instance resource type via outer alias) — block parks a real frame for the full 80ms (fail-on-pre-fix: old stubs returned in ~0ms), poll parks/wakes and lowers its ready list through guest realloc at resume, jspi:false refuses cleanly.

Gates: test-wasi-shims 50/0 (incl. iroh exec-model integration, unchanged runtime), ct-runner, ports, websocket-conformance 55/55 at unchanged wall time (14.4s vs 14.5s baseline), smoke-tls PASS. iroh-exam is environmentally broken on this machine independent of this diff (consumer checkout's prebuilt artifact stale vs its own moved WIT; redirected rebuild dies at cargo --locked before any deltic code runs) — needs an operator pull/rebuild of ~/p/polymorph/polymorph-iroh.

…n (A5)

Track 2, scoped to the known consumer (polymorph-iroh's upstream-iroh
class: unmodified iroh/tokio parking its reactor in wasi:io/poll with
timer + socket pollables). What that consumer needs, and what ships:

- Pollable over host-supplied readiness: publicly constructible
  (new Pollable(ready, wait)) — the interop seam for external providers
  (the consumer's sockets glue, deliberately outside this package, mints
  pollables the kernel polls uniformly; wait() follows the promise-swap
  producer shape, spurious wakes fine). @suspending block() with a sync
  fast path; Pollable.timer(deadline, now) armed lazily on first wait,
  readiness by clock so the wake is exact.
- poll(): sync fast path (indices return without a suspension when
  anything is ready — the per-declaration granularity A1 was designed
  for, vs jco's transpile-time asyncWasiImports), race-and-recheck park
  otherwise, unbranded throw on the empty list (io.wit's trap).
- monotonic-clock@0.2 subscribe-instant/duration mint real timers — the
  always-ready timer stub was the livelock half for a sleeping reactor.
- Streams stay buffer-backed (known consumers do no stream I/O; bytes
  ride datagrams).

ALWAYS ON, not an opt-in profile (operator ruling): the A1/A2 machinery
provides the optionality at the right layer already. On engines without
JSPI, chooseMode degrades to plain and everything behaves like the old
stubs until a guest genuinely parks — which then raises a clean
NeedsJspi at the park site instead of livelocking; jspi:false is the
per-instantiation opt-out. The retired framing ("three tiers", "never
(c) in this package") is superseded by embedder-api.md amendment A5;
intrinsics.md records the narrowed zero-cost pin (sync-only AND no
marked providers).

Pins:
- tests/blocking_test.ts (kernel): default-ready sync block; timer
  parks ~60ms and flips ready; externally-woken promise-swap pollable;
  poll fast path returns synchronously; poll parks and wakes with the
  ready index; empty-list trap.
- tests/blocking_guest_test.ts + testdata/blocking-guest.wat (through a
  REAL guest frame; the fixture shares the pollable resource type across
  the two imported instances via an outer alias, like real wasip2
  components): pollable.block (an A2-marked resource method) parks the
  frame for the full 80ms — FAIL-ON-PRE-FIX: the old stubs returned in
  ~0ms; poll parks, wakes, and lowers its ready list through guest
  realloc at resume time; jspi:false refuses the park cleanly.

Gates: test-wasi-shims 50/0 (incl. the iroh exec-model integration,
green under the always-on kernel at unchanged runtime), test-ct-runner,
test-ports, websocket-conformance 55/55 at unchanged wall time (14.4s vs
14.5s baseline — the mode flip is timing-invisible for the callback-ABI
consumers), smoke-tls suites PASS. iroh-exam is environmentally broken
on this machine independent of this diff: the consumer checkout's
prebuilt endpoint artifact is stale against its own moved WIT surface
and the redirected rebuild fails at `cargo --locked` before any deltic
code runs (consumer tree needs an operator pull/rebuild; tree verified
clean before/after).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant