fibers: checkpoint + plan for B1.5a/B1.4a; next is B1.4b (deterministic-sim Io)

This commit is contained in:
agra
2026-06-21 18:44:11 +03:00
parent 8367ad18b1
commit 02ab077bfb
2 changed files with 239 additions and 32 deletions

View File

@@ -1,17 +1,20 @@
# PLAN-FIBERS — Stream B1 (fibers + Io + M:1 scheduler)
> **STATUS: 🚧 in progress.** B1.0 (`abi(.naked)`) ✅ + B1.1 (per-fiber `context`) ✅. **B1.2**
> (`Io` interface) is **UNBLOCKED** — the earlier "blockers" were artifacts of non-idiomatic
> syntax + a worker's dirty binary. Issue **0151 was INVALID** (the `($A)->$R` bare-fn-ptr
> form is not idiomatic sx) and is **removed**. The correct `async` idiom **works today, no
> compiler change**: `async :: (io, worker: Closure(..$args) -> $R, ..$args) -> Future($R)`
> with a **lambda worker** + the `result : Future($R) = ---; result.v = worker(..args);` build
> form (mirrors the canonical `examples/0543-packs-canonical-map.sx`). Caveats: lambda params
> must be annotated; passing a bare *named* fn as the worker is non-idiomatic (use a lambda).
> Issue **0150** (`void` struct field SIGTRAP, exit 133) is a **real** bug but only hit by
> `Future(void)`/`timeout` — **deferred** (avoid void Futures in B1.2; revisit in B1.4). Resume
> B1.2 with the corrected idiom (the WIP at `.sx-tmp/b12-wip/` has the Io-protocol/Context/
> materializer parts that WORK; rewrite the async layer to the pack-lambda form above).
> **STATUS: 🚧 in progress.** B1.0 (`abi(.naked)`) ✅ · B1.1 (per-fiber `context`) ✅ · B1.2
> (`Io` interface + `async`/`await`/`cancel` over blocking `CBlockingIo`) ✅ · B1.3 (fiber
> runtime: naked `swap_context` + §10.7 stress gate + guarded `mmap` stacks, proven on aarch64
> AND x86_64/Win64) ✅ · **B1.5a (M:1 scheduler CORE — `std/sched.sx`: `spawn`/`yield_now`/
> `suspend_self`/`wake`/`run`) ✅** (fixed blocker 0154) · **B1.4a (suspending fiber-task async —
> `sched.go`/`wait`/`cancel` over `Task($R)`, nullary-thunk) ✅** (adversarially reviewed; fixed
> blockers 0156-Part1 + 0157 en route; locked `1813`).
> **→ NOW: B1.4b** — the deterministic-sim `Io` (virtual clock + timer min-heap, calibrated against
> blocking — §8.1.3, the KEYSTONE test harness). Then B1.4c (event-loop `Io`), B1.5 (end-to-end M:1
> under deterministic `Io`). Detailed progress in [CHECKPOINT-FIBERS.md](CHECKPOINT-FIBERS.md).
> NOTE: the suspending async is `sched.go`/`wait` (M:1, receiver-driven), NOT routed through the
> erased `context.io` (avoids forcing sched.sx into every std consumer + the `_fib_tramp` dup-symbol
> trap); the `Io` protocol's `spawn_raw`/`suspend_raw`/`ready` stay reserved for M:N. Deferred:
> issue 0150 (`Future(void)`/`timeout`); 0156-Part2 (deferred `..` spread); the `::` callable-param
> feature.
Carved from [PLAN-POST-METATYPE.md](PLAN-POST-METATYPE.md) Stream B (§B1) + the
design-of-record [../design/execution-evolution-roadmap.md](../design/execution-evolution-roadmap.md)
@@ -198,18 +201,28 @@ API surface. xfail→green via an `18xx` example exercising the blocking `Io` de
suspend lands in B1.3). No compiler change expected; if a protocol-in-context gap appears,
file it.
### B1.3 — A2: fiber runtime (naked switch + bootstrap + guarded `mmap` stacks)
- **B1.3a (switch-stress harness FIRST)** the standalone 2-fiber ping-pong harness
(register + canary survival, deep chains) per §10.7. This is A2's gate and predates the
scheduler + deterministic `Io`. Arch-gated run test (matching-host run; ir-only elsewhere).
- **B1.3b** — fiber bootstrap + `mmap` stacks **with guard pages** (mandatory — §8.1.1).
- (Cadence inside B1.3 follows lock→green per sub-piece; the asm switch is the highest-risk
artifact — review adversarially, with a worker if authorized.)
### B1.3 — A2: fiber runtime (naked switch + bootstrap + guarded `mmap` stacks) — ✅ COMPLETE
- **B1.3a (switch-stress harness FIRST) — ✅** the §10.7 register/canary-survival gate (1807/1808),
validity proven by negative controls, adversarially reviewed.
- **B1.3b — ✅** fiber bootstrap + guarded `mmap` stacks (1809); the x86_64 sibling landed as Win64
on a real VM (1810, `0 0 P`). Switch proven on TWO arch/ABI pairs.
### B1.4A3: `Io` impls (blocking → deterministic-sim KEYSTONE → event-loop)
Blocking first; then the deterministic-sim `Io`, **calibrated against blocking** before any
`18xx` test trusts it; then the event loop. The deterministic `Io` is the test harness for
*all* of B1.5 + Stream B2.
### B1.5aM:1 scheduler CORE (`std/sched.sx`) — ✅ COMPLETE
The reusable scheduler wrapping `swap_context`: generic `Fiber`/`Scheduler`,
`spawn`/`yield_now`/`suspend_self`/`wake`/`run` over guarded `mmap` stacks, one generic
`fib_dispatch` running any stored closure body. Adversarially reviewed + hardened; fixed blocker
bug 0154 (struct-field `null`/`---` over-store) en route. Locked by `1811` (round-robin) + `1812`
(suspend/wake). Built BEFORE the deterministic `Io` because FiberIo (B1.4a) needs it as substrate.
### B1.4a — suspending fiber-task async (`sched.go`/`wait`/`cancel`) — ✅ COMPLETE
`Task($R)` + `Scheduler.go(work) -> *Task($R)` + `wait`/`cancel` in `sched.sx` (nullary-thunk;
self-contained). `go` spawns `work` as a fiber, `wait` parks the caller until it completes. Locked
by `1813`. Two compiler blockers fixed (0156-Part1, 0157) + adversarially reviewed/hardened.
### B1.4b/c — A3: `Io` impls (deterministic-sim KEYSTONE → event-loop)
Blocking exists (io.sx `CBlockingIo`). Next the deterministic-sim `Io`, **calibrated against
blocking** before any `18xx` test trusts it; then the event loop. The deterministic `Io` is the
test harness for *all* of B1.5 + Stream B2.
### B1.5 — A5: M:1 scheduler
End-to-end validation of the colorblind stack. `18xx` corpus under the deterministic `Io`,