Skip to content
Beskid Platform specification

Beskid

Jump to a Beskid service

Beskid

Jump to a Beskid service

Fiber scheduler and stacks

Platform spec feature

Fiber scheduler and stacks

Spec standingStandard

Owner
Piotr Mikstacki
Submitter
Piotr Mikstacki

What this feature specifies

Cooperative M:N scheduling: many fibers on an OS worker pool, growable stacks (64 KiB initial, 8 MiB cap), and compiler stack maps at safepoints. fiber_* builtins back corelib Fiber<T>; main runs on fiber 0 and shutdown Joins non-Detach children. Phase A documents a single GC mutator; Phase B adds parallel mutators without API break.

Implementation anchors

  • compiler/crates/beskid_runtime/src/scheduler/ — split scheduler state, TLS, spawn/cancel, run loop, and syscall parking modules
  • compiler/crates/beskid_abi/ — symbols and BUILTIN_SPECS
  • compiler/crates/beskid_analysis/src/builtins.rs__fiber_* injected paths
  • compiler/crates/beskid_codegen/ — safepoints, stack maps

Contract statement

The Beskid runtime provides a cooperative M:N scheduler: many fibers multiplexed on a pool of OS worker threads. Fiber code uses growable stacks and compiler-emitted stack maps at safepoints. The runtime exports fiber_* builtins consumed by Fiber<T> in corelib—no async/await lowering.

Preemptive parallelism for user code uses System.Threading (OS threads), not preempted fibers in v1.

Architecture

flowchart LR
subgraph runtime [beskid_runtime]
SCH[Scheduler]
POOL[OS thread pool]
FB[fiber stacks]
SCH --> POOL
SCH --> FB
end
subgraph corelib [corelib_concurrency]
FT[Fiber T struct]
FT -->|fiber_* builtins| SCH
end
subgraph compiler [beskid_codegen]
SP[spawn lowering]
SM[stack maps]
SP --> SM
end

Phase A vs Phase B

PhaseMutator threadsGCFiber scheduler
A (v0.2 target)One GC mutator; fibers may run on multiple OS threads but GC obeys single-mutator rulesExisting arena; document barriers as no-op until Phase BCooperative; park at Send/Receive/syscall
B (documented)Multiple parallel mutatorsConcurrent mark/sweep + real gc_write_barrierOptional function-entry preemption

Phase B must be specified in memory-and-gc-runtime-contract before implementation; Phase A ships first.

Runtime builtins (normative names)

Illustrative ABI symbols (exact names in beskid_abi/src/symbols.rs):

  • fiber_spawn, fiber_spawn_with_cancel_slot, fiber_join_status, fiber_join_value, fiber_detach, fiber_cancel, fiber_yield
  • fiber_current_id (diagnostics), fiber_processor_count (scheduler sizing)
  • Monotonic clock builtin for Concurrency.NowMillis() (replaces rt_now_millis)

Deprecated: rt_yield (sched feature) → fiber_yield.

Syscall Parking

M6 completion requires blocking runtime syscalls to enqueue host blocking work on the syscall pool, park only the current fiber, and wake that fiber when the worker finishes. Worker threads must not execute generated Beskid code or perform generated-runtime allocation directly; any runtime object creation happens after the fiber resumes on the scheduler thread.

Main fiber

main() runs on fiber 0. Runtime starts scheduler before main. When main returns, the runtime Joins every spawned fiber that was not Detached, then shuts down the thread pool. Detach fibers are not joined at shutdown; their panic still aborts the process.

Stacks

  • Initial stack 64 KiB, growable, cap 8 MiB
  • Stack overflow → FiberError::StackOverflow surfaced at Join on the affected fiber (no undefined behavior)

No open decisions. Closed choices are normative ADRs under adr/ (D-EXEC-RT-0001D-EXEC-RT-0004); use the reader ADRs tab for expandable detail.

Articles