Shared mutable stacks across fibers would break GC stack maps and the memory model. The runtime must align with language channel-only rules.
Channels and synchronization
Platform spec feature
Channels and synchronization
Spec standingStandard
-
Runtime enforces queue transfer; stack pointers must not cross fibers.
Context
Decision
Rule Detail Mechanism Channels are the only approved cross-fiber data transfer at runtime Happens-before Successful Send happens-before Receive that observes the value Values Copied or heap handles with GC tracing — no stack pointer transfer Builtins channel_*,mutex_*,wait_group_*implement queues and coordinationCompiler Must not lower cross-fiber stack sharing Corelib policy: D-CORE-CONC-0009.
Consequences
New sync primitives require spec + ABI + corelib trifecta before export.
Verification anchors
beskid_runtimechannel tests; git12ee673. -
Per-hub cursor scans registered channels to avoid starvation.
Context
Multiplexing without language
selectneeds deterministic fairness when one registered channel is always ready.Decision
Rule Detail Homogeneity Hub<T>— homogeneousTonly in v1Scan Cursor starts at k; scank, k+1, …modulo registration count for first ready channelAfter success Cursor advances past chosen index (wrap) v1 scope WaitSend out of scope; no language selectEmpty hub WaitReceive with zero registrations → HubError::EmptyMatches D-CORE-CONC-0003.
Consequences
Runtime
hub_wait_receive_*implements rotation; corelib documents registration limits for hot paths.Verification anchors
Hub builtins; corelib hub tests.
-
Closed, full, and cancelled operations surface as Result/Option at the FFI boundary.
Context
Panicking on backpressure or closed channels makes cooperative code fragile and inconsistent with corelib
Resulttypes.Decision
Operation Runtime behavior Send after Close Closedin ResultReceive on closed empty ClosedTrySend / TryReceive Optionfor full/emptyCancel Parked ops wake with Cancelledafter childOnCancelledJoin on cancelled child FiberError::CancelledPanic Forbidden for ordinary channel/hub/mutex errors Aligns with D-CORE-CONC-0005.
Consequences
Builtin implementations and corelib wrappers must share error enums. Duplicate Close is idempotent-safe.
Verification anchors
Contracts and edge cases; concurrency runtime tests.
0 revisions (git unavailable at build; counts may be empty)
No commits recorded for this path.
| Section id | Required | Found |
|---|---|---|
what-this-feature-specifies | yes | yes |
implementation-anchors | yes | yes |
Full tree: run pnpm verify:platform-spec-layout (writes src/generated/platform-spec-layout-report.json).
What this feature specifies
Runtime channel queues (Send, Receive, TrySend, TryReceive, Close), homogeneous Hub<T> multiplexing with round-robin WaitReceive, and Mutex / WaitGroup coordination. Cross-fiber data transfer is channel-only; successful Send happens-before observing Receive. Cancellation unblocks parked ops with Cancelled in Result after OnCancelled on the child fiber.
Implementation anchors
- Builtins:
channel_*,hub_*,mutex_*,wait_group_*incompiler/crates/beskid_runtime/ - ABI registry:
compiler/crates/beskid_abi/src/symbols.rs,define_builtins! - Corelib mapping: Concurrency package
Contract statement
Channels are the only approved mechanism for passing data between fibers. The runtime implements bounded/unbounded queues with Send and Receive (full method names in corelib). Hub multiplexes many channels without a language select. Mutex and WaitGroup builtins back corelib structs.
Errors use Result / Option—never panic for closed, full, or cancelled operations.
Happens-before
A successful Send on Channel<T> happens-before a Receive that observes the value (Go/Java memory model style). Compiler must not allow passing stack pointers through Channel; values are copied or heap handles with GC tracing.
Phase B parallel mutators rely on these edges plus gc_write_barrier on pointer stores.
Hub
Hub<T> maintains registered (index, channel: Channel<T>) pairs — homogeneous T only in v1. WaitReceive blocks until at least one member has a message available, then completes a Receive on that member.
Fairness (normative): round-robin — per-hub cursor starts at 0, scans registered indices in ascending order wrapping modulo registration set, chooses the first ready channel in that rotation. After success, cursor advances past the chosen index. Prevents starvation when a high-traffic channel is registered before a low-traffic one.
flowchart LR
subgraph hub [Hub T cursor = k]
c0[ch0]
c1[ch1]
c2[ch2]
end
scan[Scan k, k+1, k+2 mod n for ready]
recv[Receive on first ready]
advance[cursor := index+1 mod n]
c0 --> scan
c1 --> scan
c2 --> scan
scan --> recv --> advanceWaitSend is out of scope for v1. No language select in v1.
Full decision log: Concurrency package / decisions record.
Runtime builtins
channel_create,channel_send,channel_receive,channel_try_send,channel_try_receive,channel_closehub_create,hub_register,hub_wait_receive, …mutex_lock,mutex_unlock,wait_group_add,wait_group_done,wait_group_wait
Cancellation
Section titled “Cancellation”Fiber.Cancel sets cancellation flag, dispatches OnCancelled on the child fiber (language event on Fiber<T>), then unblocks parked Receive/Send/Wait with Cancelled in Result. Join on the child returns FiberError::Cancelled.
Blocking IO
Syscall and console blocking must integrate with channel parking: producers Send bytes/events; consumers Receive on fibers. Raw syscall blocking on a fiber must park that fiber and offload blocking to the OS thread pool.
Decisions
Section titled “Decisions”No open decisions. Closed choices are normative ADRs under adr/ (D-EXEC-RT-0011 … D-EXEC-RT-0013); use the reader ADRs tab for expandable detail.