wasm-posix-host
    Preparing search index...

    Class CentralizedKernelWorker

    Index

    Constructors

    Properties

    relistenBatchSize: number = 64

    How many syscalls to process via microtask before yielding to the event loop via setImmediate. Default 64 is tuned for Node.js. The dedicated browser worker sets this to 1 so worker messages keep progressing.

    usePolling: boolean = false

    When true, use a MessageChannel-based poller to check all channels instead of per-channel Atomics.waitAsync listeners.

    This avoids a V8 bug where Atomics.waitAsync microtask chains from multiple concurrent processes freeze the main thread. The poller uses MessageChannel for ~0ms dispatch (bypassing the browser's 4ms timer clamp on setTimeout/setInterval), with periodic setTimeout yields every 4ms to keep timers and rendering alive.

    This remains a legacy opt-in for browser embeddings that run the kernel on the main thread. The dedicated browser worker and Node.js both keep the default event-driven Atomics.waitAsync mode.

    Accessors

    • get bos(): GbmBoRegistry

      Live /dev/dri/renderD128 GBM bos. Pixel storage for a bound bo lives in the owning process's wasm Memory at the binding range; consumers read pixels by projecting [addr, addr+len) onto the SAB returned by getProcessMemory(pid).

      Returns GbmBoRegistry

    • get framebuffers(): FramebufferRegistry

      Live /dev/fb0 mappings reported by the kernel, indexed by pid. Renderers (canvas in browser, no-op in Node) read from this on each frame; the kernel populates it via the host_bind_framebuffer import.

      Returns FramebufferRegistry

    Methods

    • Append data to a process's stdin buffer without marking stdin as a pipe. Used for interactive stdin where data arrives incrementally. Wakes any blocked stdin readers after appending.

      Parameters

      • pid: number
      • data: Uint8Array

      Returns void

    • Register an OffscreenCanvas (and optional stats SAB) as the scanout target for a CRTC. Starts the vblank pump on first attach.

      opts.mode selects how the canvas is painted:

      • "auto" (default): the pump never grabs a 2D context. If the DRM-master pid later calls eglCreateContext, the GL bridge's auto-attach path claims the canvas for WebGL2 and the user program paints directly. Slots 5/6 (commit count, last µs) still tick from kernel-side PAGE_FLIP state.
      • "2d": legacy CPU-blit path. The pump eagerly grabs 2D here and copies the kernel's scanout BO into the canvas each frame. Used by demos that render into the FB via memcpy rather than GL.
      • "webgl2": marks the canvas as GL-owned up front. Pump never blits. Same effect as auto + a later markKmsCanvasGlOwned, but spares the GL bridge from racing the pump's 2D acquisition.

      Parameters

      • crtc_id: number
      • canvas: OffscreenCanvas
      • OptionalstatsSab: SharedArrayBuffer
      • Optionalopts: { mode?: "2d" | "webgl2" | "auto" }

      Returns void

    • Attach a stats SAB for a CRTC without registering a scanout canvas. Slots 5/6 (kernel commit count + last-frame µs) are populated by the vblank pump regardless of whether the same crtc owns a blit target. Used by demos that render through the GL bridge while still driving real drmModePageFlip ioctls.

      Parameters

      • crtc_id: number
      • statsSab: SharedArrayBuffer

      Returns void

    • Consume a host-side clone attachment proof and attach its one channel.

      PID, TID, process-memory generation, and pthread fork context all come from the capability's private WeakMap record. The caller chooses only the transport mailbox it allocated; it cannot name a task or copy/reuse an attachment object to create another authority.

      Parameters

      Returns void

    • Channel count the program last configured on /dev/dsp.

      Returns number

    • Bytes buffered in the /dev/dsp ring waiting to be drained.

      Returns number

    • Sample rate (Hz) the program last configured on /dev/dsp.

      Returns number

    • Ask the Rust kernel to allocate and create a process descriptor.

      The returned PID already names authoritative kernel state. Hosts may attach memory, channels, and a Worker to it, but never choose the PID.

      Parameters

      • stdio: RegisterProcessStdio

      Returns number

    • Parameters

      • pid: number
      • OptionalexpectedMemory: Memory

      Returns boolean

    • Drain up to out.byteLength bytes of PCM audio buffered in /dev/dsp into out. Returns the number of bytes copied, always a multiple of the active frame size (2 bytes mono / 4 bytes stereo).

      The host typically drives this from an AudioWorkletNode or AudioBufferSourceNode scheduler that pulls samples at the rate an AudioContext reports. The kernel ring drops oldest frames on overflow rather than blocking, so falling behind a few RAFs costs audio but never wedges DOOM.

      Parameters

      • out: Uint8Array

      Returns number

    • Dump syscall profiling data to stderr. Call from your serve script: process.on('SIGINT', () => { kernelWorker.dumpProfile(); process.exit(); });

      Only produces output when WASM_POSIX_PROFILE=1 env var is set.

      Returns void

    • Replace the parked success result of a clone whose deferred thread Worker could not be constructed. The entry layer separately rolls back ThreadInfo, channel, allocator, and Worker registries before this completion publishes.

      Parameters

      • pid: number
      • tid: number
      • errno: number

      Returns boolean

    • Forget mappings and detach SysV segments after the irreversible kernel exec commit. A failure here is post-commit and must be treated as fatal by the caller; returning to the discarded image is no longer possible.

      Parameters

      • pid: number

      Returns number

    • Finalize a signal death that occurred while exec had no registered host channel. The kernel Process is already an Exited zombie; this performs the parent notification and host exit callback exactly once. The caller must not install a replacement worker when the returned signal is positive.

      Parameters

      • pid: number

      Returns number

    • Finalize a signal that reached a fork/spawn child while its async Worker launch had no dispatchable channel. The child remains a real zombie for parent wait semantics, but eager host fd mirrors must be retired.

      Parameters

      • pid: number

      Returns number

    • Complete kernel-side cleanup for a thread whose worker has stopped. Normal pthread exit reaches this from SYS_EXIT. Crash paths use the same cleanup so pthread_join waiters do not stay blocked on CLONE_CHILD_CLEARTID.

      Both identifiers matter: channelOffset removes the host mailbox/fork context, while tid addresses the kernel/libc thread state and clear-TID futex word used by joiners.

      Parameters

      • pid: number
      • tid: number
      • channelOffset: number

      Returns void

    • Release the exec guard only after the outer worker generation is installed.

      Parameters

      • pid: number

      Returns void

    • Per-process fork counter (parent side, incremented inside kernel_fork_process on success). Used by the spawn regression tests to assert that a SYS_SPAWN call did NOT fall back to the fork path.

      Returns u64::MAX (as bigint) if the pid does not exist; callers should compare against an explicit before-value rather than treating "no process" as "0 forks".

      Parameters

      • pid: number

      Returns bigint

    • ABI version the kernel advertised at startup via its __abi_version export. Worker processes compare against this and refuse to run programs built against an incompatible ABI.

      Returns number

    • Get the kernel Wasm instance.

      Returns Instance | null

    • Current size of the kernel's own Wasm linear memory in 64 KiB pages.

      This deliberately reports kernel memory, not any guest process memory. Hosts use it for bounded-lifetime diagnostics such as proving that repeated pipe/fork teardown reuses allocator-owned chunks.

      Returns number

    • Return the wasm Memory for pid (or undefined if no such process is registered). Renderers use this to build typed-array views over the bound framebuffer region.

      Parameters

      • pid: number

      Returns Memory | undefined

    • Inherit host-side shared-memory metadata after the child process memory has been registered, but before its Worker starts executing.

      Parameters

      • parentPid: number
      • childPid: number

      Returns void

    • Initialize the kernel. Loads kernel Wasm and validates the host adapter ABI.

      Parameters

      • kernelWasmBytes: BufferSource

      Returns Promise<void>

    • Push a mouse event into the kernel's /dev/input/mice queue. The kernel buffers a 3-byte PS/2 frame; any process blocked in read() or poll() on the device is woken on the next retry tick.

      Parameters

      • dx: number
      • dy: number
      • buttons: number

      Returns void

    • True while exec has committed but the replacement channel is not installed.

      Parameters

      • pid: number

      Returns boolean

    • Public liveness guard for async Node/browser worker-entry continuations.

      Parameters

      • pid: number

      Returns boolean

    • Validate the exec caller and apply deferred posix_spawn file actions. This is the fallible kernel preflight; no image-owned state is discarded.

      Parameters

      • pid: number
      • callerTid: number

      Returns number

    • Run kernel-side exec setup: close CLOEXEC fds, reset signal handlers. Returns 0 on success, negative errno on failure. Called by onExec callbacks after confirming the target program exists.

      Parameters

      • pid: number
      • callerTid: number

      Returns number

    • Host-teardown reclamation.

      [JSC-TERMINATE-ATOMICS-WAIT-LEAK] — WORKAROUND, remove when the engine bug is fixed; see docs/jsc-terminate-atomics-wait-workaround.md.

      On JSC (Safari, and Bun via bun's JavaScriptCore), Worker.terminate() cannot kill (or free the memory of) a worker parked in Atomics.wait on its syscall channel — which is where every idle/blocked process worker sits (accept, read, poll, select, sleep, futex, the channel round-trip). Terminating them directly leaks their threads + committed working set, so each image switch accumulates a whole machine and the tab OOMs. V8 (Chrome, Node) interrupts the wait on terminate and reclaims, so this is a no-op cost there and is invoked unconditionally by both host entries for parity.

      For every worker currently parked at CH_PENDING we complete its syscall with EINTR AND queue a SIGKILL into the channel signal slot. The glue's __deliver_pending_signal (run right after the syscall returns) sees SIGKILL and calls the kernel_exit import directly (NOT musl _exit(), which would re-park the worker in the SYS_exit spin loop) → the unreachable trap that worker-main catches → the worker posts {exit} and returns to its JS event loop, where the host's terminate() (or the {exit} handler) can finally reclaim it.

      SIGKILL is never delivered to the guest in normal operation (it is uncatchable — the kernel enforces the default terminate action itself), so the glue treats a queued SIGKILL unambiguously as "exit now".

      Returns Set<number>

    • Notify the kernel that a host worker for pid died asynchronously (uncaught wasm trap, instantiation failure, externally terminated Worker) WITHOUT going through the normal SYS_EXIT_GROUP path.

      Without this, an OOB/instantiation crash leaves the kernel believing the process is still alive: any concurrent waitpid in the parent then blocks until host destroy. P-06 / K-03 exposed this — the child's wasm trapped during _start, the worker reported it via {type:"error"}, the host posted stderr + deactivated the process locally, but the kernel never marked the pid as a zombie or woke the parent.

      Marks the process as signal-terminated in Rust using signum (default SIGSEGV = 11), queues SIGCHLD on the parent, and wakes any parked waitpid / waitid.

      Idempotent via hostReaped: if the kernel already saw a clean SYS_EXIT for this pid, this is a no-op (the kernel's exit status wins). Host-side cleanup (channel removal, timer cancellation) is still the caller's responsibility — call deactivateProcess after this if the pid is going away.

      Parameters

      • pid: number
      • signum: number = 11

      Returns void

    • Public wake helper for host-side pipe writes (TCP bridges, HTTP bridges, etc.). Call this AFTER directly writing into a pipe via kernel_pipe_write or kernel_inject_connection.

      In order:

      1. Wake any process blocked in read/recv on this pipe (pendingPipeReaders).
      2. Wake any process blocked in poll/ppoll/pselect6 whose pipeIndices includes this pipe (pendingPollRetries). Pass pidFilter only when ownership cannot be shared. Accepted TCP pipes omit it because fork children can inherit the same connection.
      3. Schedule a broad wake (scheduleWakeBlockedRetries) for everything else.

      Without step 2, blocked pollers wait for the fallback timer in handleBlockingRetry to fire, which is the bug behind PR fixing the WordPress LAMP demo's slow install.php (see commit history).

      Parameters

      • pipeIdx: number
      • OptionalpidFilter: number

      Returns void

    • Public wake helper for host-side pipe reads (response pump in the TCP/HTTP bridges). Call this AFTER directly reading data from a pipe so any process blocked writing because the pipe was full can resume, plus a broad wake.

      Parameters

      • pipeIdx: number

      Returns void

    • Notify the kernel that a thread has exited. Removes thread state from the process's thread table.

      Parameters

      • pid: number
      • tid: number

      Returns void

    • Register a callback for PTY output data.

      Parameters

      • ptyIdx: number
      • callback: (data: Uint8Array) => void

      Returns void

    • Pick the next listener target for a port via round-robin. Only considers processes that are still registered.

      Public so external callers (the in-kernel HTTP request bridge) can resolve a port to a {pid, fd} before injecting a connection.

      Parameters

      • port: number

      Returns { fd: number; pid: number } | null

    • Flush mappings owned by the address space that exec is about to discard. Tracking and SysV attachments remain intact until the kernel commit succeeds, so a failed exec can continue using the old address space.

      Parameters

      • pid: number

      Returns number

    • Remove old channel/registration state for a process about to exec. Does NOT remove from kernel process table (exec keeps the same pid). Preserves alarm()/ITIMER_REAL, but cancels timer_create() timers: POSIX keeps interval timers across exec and deletes per-process POSIX timers.

      Parameters

      • pid: number
      • OptionalexpectedMemory: Memory

      Returns boolean

    • Read all available data from a PTY master (slave output → host). Returns data or null if empty.

      Parameters

      • ptyIdx: number

      Returns Uint8Array<ArrayBufferLike> | null

    • Write data to a PTY master (host → line discipline → slave). Wakes any process blocked on reading the slave side.

      Parameters

      • ptyIdx: number
      • data: Uint8Array

      Returns void

    • Resize a PTY and send SIGWINCH to the foreground process group.

      Parameters

      • ptyIdx: number
      • rows: number
      • cols: number

      Returns void

    • Read /proc/[pid]/maps for a foreign process. Returns the raw Linux- style text (one line per mapped region) or null if the pid doesn't exist. Empty string if the process has no mappings.

      Parameters

      • pid: number

      Returns string | null

    • Attach process memory and thread channels to an existing kernel Process. Each channel is a region in the process's shared Memory.

      Parameters

      • pid: number
      • memory: Memory
      • channelOffsets: number[]
      • Optionaloptions: RegisterProcessOptions

      Returns void

    • Remove a channel from a process registration (e.g. when a thread exits).

      Parameters

      • pid: number
      • channelOffset: number

      Returns void

    • Remove a process from the kernel's PROCESS_TABLE. Called when a zombie is reaped by wait/waitpid.

      Parameters

      • pid: number

      Returns void

    • Remove a pid from the wasm kernel's ProcessTable entirely. Used by the worker-entry's crash path: when a worker dies via a wasm trap (signature mismatch, OOM, etc.) the kernel never saw a SYS_EXIT, so its ProcessTable still has the pid in state=Running. After this runs, kernel_enum_procs no longer reports it and a parent's waitpid() returns ECHILD — accurate for "the process really is gone."

      Don't call this for normal exits — the kernel marks those Exited (zombie) so the parent can still reap.

      Parameters

      • pid: number

      Returns void

    • Parameters

      • pid: number
      • len: number

      Returns number

    • Parameters

      • pid: number
      • addr: number
      • len: number

      Returns number

    • Send an HTTP/1.1 request to a server running inside the kernel and resolve with the parsed response. Bypasses real TCP — uses kernel_inject_connection + kernel_pipe_* directly.

      Used by both the browser service-worker bridge and the Node host's fetchInKernel API (see docs/plans/2026-04-30-external-kernel-http-request-interface.md).

      Parameters

      • port: number
      • request: HttpRequest
      • opts: SendHttpRequestOptions = {}

      Returns Promise<HttpResponse>

    • Set the program's initial brk. Compact process layouts pass the first guest-managed byte after the host control slab; legacy callers may pass the program's __heap_base directly. Must run before the new process worker can issue its first syscall.

      Accepts bigint (preferred — what extractHeapBase returns) or number. The kernel export takes a usize, whose JS representation depends on the kernel wasm pointer width.

      Parameters

      • pid: number
      • addr: number | bigint

      Returns boolean

    • Set the program-break ceiling for a process. Hosts use this to reserve low in-memory control pages for syscall channels and pthread TLS without letting brk grow into them.

      Parameters

      • pid: number
      • brkLimit: number

      Returns boolean

    • Set a freshly-created process's initial real/effective uid and gid. Must be called after registerProcess and before the process starts.

      Parameters

      • pid: number
      • ids: { gid?: number; uid?: number }

      Returns void

    • Set the working directory for a process. Must be called after registerProcess and before the process starts.

      Parameters

      • pid: number
      • cwd: string

      Returns void

    • Set the mmap address space ceiling for a process. Must be called before the process worker starts to prevent mmap from allocating in the thread channel/TLS region.

      Parameters

      • pid: number
      • maxAddr: number

      Returns void

    • Set the automatic mmap lower bound for a process. Compact process layouts set this to the first guest-managed byte after the host control prefix.

      Parameters

      • pid: number
      • mmapBase: number

      Returns boolean

    • Set stdout/stderr capture callbacks on the underlying kernel instance. Must be called after construction but works at any time.

      Parameters

      • callbacks: { onStderr?: (data: Uint8Array) => void; onStdout?: (data: Uint8Array) => void }

      Returns void

    • Provide data that will be returned when the process reads from stdin (fd 0). Data is returned in chunks until exhausted, then EOF is returned. Must be called before the process starts reading stdin.

      Parameters

      • pid: number
      • data: Uint8Array

      Returns void

    • Release waitAsync listeners after the corresponding guest Worker stopped.

      Atomics.waitAsync has no cancellation API. Engines retain its unresolved Promise in a global waiter registry, and the Promise reaction closes over channel, pinning the process's entire Shared WebAssembly.Memory even after every ordinary host map has released it. Notify only after Worker termination: while a guest is live, it can also be waiting on CH_STATUS.

      The exact retired token remains until every pending listener callback has run and acknowledged the stale generation. Pool owners can await the returned Promise before reusing the backing or pthread slot.

      Parameters

      • pid: number
      • OptionalexpectedMemory: Memory
      • OptionalexpectedChannelOffset: number

      Returns Promise<void>

    • Create a PTY pair and wire fds 0/1/2 of pid to the slave side. Returns the PTY index, or throws on failure.

      Parameters

      • pid: number

      Returns number

    • Decide whether an asynchronously created fork/spawn child may receive a host Worker. A child killed before registration remains a real, waitable kernel zombie; finalize its host-only state without rolling it back.

      Parameters

      • pid: number

      Returns boolean

    • Start a prepared process/thread Worker only when the authoritative kernel Process is runnable. Fork/spawn/exec setup may register memory and return to its caller while stopped; the constructor itself is retained here so no guest instruction can execute before SIGCONT. expectedMemory is the generation token that prevents a deferred closure from attaching to a later exec image for the same persistent PID.

      Parameters

      • pid: number
      • expectedMemory: Memory
      • start: () => void
      • cancel: () => void
      • OptionalonStartError: (error: unknown) => boolean

      Returns ProcessWorkerStartDisposition

    • Whether this kernel supports lossless bounded argv+environment replacement.

      Returns boolean

    • Parameters

      • value: number | bigint

      Returns KernelPointer

    • Unregister a process. Stops listening on its channels and removes it from the kernel's process table.

      Parameters

      • pid: number
      • OptionalexpectedMemory: Memory

      Returns boolean

    • Side-effect-free exec argv/environment validation. Call this before the irreversible exec commit so oversized metadata returns E2BIG to the old image instead of failing while the replacement worker is being installed.

      Parameters

      • argv: readonly string[]
      • env: readonly string[]
      • ptrWidth: 4 | 8 = 4

      Returns number

    • Cooperatively unwind the exact browser Worker generation discarded by exec without exiting the persistent kernel Process.

      Every parked channel receives an internal SIGKILL marker plus EINTR. The guest glue enters its existing non-returning kernel_exit import; worker-main recognizes the exec marker, skips SYS_EXIT, and returns so the browser wrapper can publish an exact memory_quiescent ownership fence.

      Parameters

      • pid: number
      • expectedMemory: Memory

      Returns Set<number>