plan: correct grounded errors + harden async streams (post-metatype review)
Fold the adversarial-review corrections into the program plan + design-of-record: - atomics is 100% net-new (no scaffolding; lower.zig 'ordering' is comparison-only) - context is already an implicit *Context param (not TLS) — B1.1 rescoped - abi(.pure) exists but is inert (no naked emission) — B1.0 rescoped - B1.3 switch-stress harness is the first deliverable + mandatory stack guards - Stream C gated on a named TSan/ASan + run-N stress harness, not a footnote
This commit is contained in:
@@ -34,8 +34,12 @@ earlier if FFI/`#compiler`-collapse becomes a priority).
|
||||
## Stream A — ATOMICS (N1) · `PLAN-ATOMICS.md` when carved
|
||||
|
||||
**Goal:** LLVM atomic codegen — the net-new emit primitive. Surface = `Atomic($T)`
|
||||
wrapper + `Ordering` enum (locked, design §4.6). Some IR/inference scaffolding exists;
|
||||
**lowering is absent**.
|
||||
wrapper + `Ordering` enum (locked, design §4.6). **Grounding correction: this is 100%
|
||||
net-new — there is NO atomics scaffolding.** `Atomic`/`Ordering` exist nowhere in
|
||||
`library/` (the only `thread.sx` hit is the word "Atomically" in a comment), and the
|
||||
only "ordering" in `lower.zig:1400-1418` is **comparison** ordering (`< <= > >=`),
|
||||
entirely unrelated to memory ordering — do not mistake it for groundwork. A.0 must
|
||||
build the type, the IR op, inference, AND lowering from zero.
|
||||
|
||||
**Phases:**
|
||||
- A.0 `Atomic($T)` + `Ordering` lib types + `load`/`store` → LLVM `load atomic`/`store
|
||||
@@ -57,24 +61,50 @@ The colorblind, stackful, pure-sx async runtime (design §4). Compiler floor is
|
||||
the runtime is sx lib. Likely carved as two PLANs:
|
||||
|
||||
### B1 — Fibers + Io + M:1 (the runtime; `PLAN-FIBERS.md`)
|
||||
- B1.0 **`callconv(.naked)`** — extend `CallConv {default, c}` (types.zig:169) + skip
|
||||
prologue/epilogue lowering. (Net-new; gates the context-switch.)
|
||||
- B1.1 **Repointable-`context` codegen** — lower `context` as a swappable indirection
|
||||
(never raw TLS) + per-fiber stack-limit. **Prerequisite of B1.3, not a successor.**
|
||||
- B1.0 **`abi(.naked)` — make the EXISTING `.pure` ABI actually naked.** The enum
|
||||
already carries `.pure` (ast.zig:142, documented "pure/naked, no prologue/epilogue"),
|
||||
but it is an **inert label today**: `type_resolver.zig:237` maps `.pure → .default`
|
||||
CC and there is **zero naked-attribute emission in emit_llvm**. So B1.0 is NOT
|
||||
"extend the enum" (done) — it is "emit the LLVM `naked` attr + skip prologue/epilogue
|
||||
lowering for `.pure`," genuinely net-new. (Roadmap §7-step-4's "extend
|
||||
`CallConv {default, c}`" is stale — CallConv was renamed ABI and already gained
|
||||
`compiler`/`pure` in the compiler-API stream.) Gates the context-switch.
|
||||
- B1.1 **Per-fiber `context` root + `push Context`-stack storage.** Grounding correction:
|
||||
`context` is **already an implicit `*Context` parameter** (comptime_vm.zig:392,
|
||||
lower.zig:257 "Implicit Context parameter machinery"), **not raw TLS** — so it already
|
||||
rides the fiber stack and the design doc's "lower as swappable indirection, never raw
|
||||
TLS" guards a non-problem. The **real, currently-unsized** scope is: (a) where a
|
||||
freshly-spawned fiber's *root* `Context` comes from, and (b) where the `push Context`
|
||||
stack frames live (if on the caller stack, fiber-local for free; if a global root,
|
||||
that root must become per-fiber). **Ground the current mechanism FIRST** — B1.1's size
|
||||
is unknown until then, and it may be much smaller than the prior "M" estimate.
|
||||
**Prerequisite of B1.3, not a successor.**
|
||||
- B1.2 **A1 — `Io` interface + `context.io` + `Future` + `cancel()` API** (protocol/
|
||||
vtable threaded like `Allocator`).
|
||||
- B1.3 **A2 — fiber runtime**: `callconv(.naked)` context-switch asm (per-arch),
|
||||
bootstrap, `mmap` stacks. **sx lib, not a compiler builtin** (design §4 A2).
|
||||
- B1.3 **A2 — fiber runtime**: `abi(.naked)` context-switch asm (per-arch), bootstrap,
|
||||
`mmap` stacks **with mandatory guard pages** (NOT optional — a fixed-stack fiber that
|
||||
overflows without a guard corrupts adjacent fiber memory silently; §8.1.1). **sx lib,
|
||||
not a compiler builtin** (design §4 A2). **First deliverable of B1.3, before the
|
||||
scheduler AND before the deterministic `Io`: a standalone 2-fiber ping-pong
|
||||
switch-stress harness** (scribble every callee-saved reg + a stack canary before each
|
||||
suspend, deep/recursive fiber chains, verify all survive post-resume — §10.7). It
|
||||
needs no scheduler and is the *only* gate that catches a one-register slip; A2 is
|
||||
untestable by the deterministic-`Io` harness (which tests *scheduling*, not the
|
||||
*switch*), so this harness — not B1.4 — is A2's correctness gate.
|
||||
- B1.4 **A3 — `Io` impls: blocking → deterministic-sim (KEYSTONE) → event-loop**
|
||||
(kqueue/epoll/io_uring). Build the deterministic `Io` *before* the event loop — it
|
||||
is the test harness (§10.1).
|
||||
is the test harness for *scheduling* (§10.1). (Note: the **event loop does not yet
|
||||
cooperate with a platform UI run loop** — CFRunLoop/NSRunLoop/ALooper; pinning gives
|
||||
thread-affinity, not run-loop integration. Tracked as an open design gap for the §6
|
||||
app targets, deferred out of B1.)
|
||||
- B1.5 **A5·M:1 scheduler** — validates the whole colorblind stack end-to-end.
|
||||
|
||||
**Gates:** deterministic-`Io` **calibrated** against blocking `Io` (don't trust an
|
||||
uncalibrated oracle — §8.1.3); corpus `18xx` under deterministic `Io`; **A2
|
||||
switch-stress test** (scribble every callee-saved reg + canary, deep fiber chains,
|
||||
verify post-resume — §10.7) + arch-gated run tests. A2 is the highest-corruption-risk
|
||||
piece (§8.1.1).
|
||||
**Gates:** the **B1.3 switch-stress harness is A2's gate** (register/canary survival,
|
||||
not run/snapshot — §8.1.1, §10.7) + arch-gated run tests; deterministic-`Io`
|
||||
**calibrated** against blocking `Io` (don't trust an uncalibrated oracle — §8.1.3);
|
||||
corpus `18xx` under deterministic `Io` asserts a program-emitted **ordering contract**
|
||||
(sequence markers), not raw interleaving, so scheduler-internal policy changes don't
|
||||
churn every snapshot.
|
||||
|
||||
### B2 — Channels + cancellation + stdlib (`PLAN-CHANNELS.md`)
|
||||
- B2.0 **N3 — channels** (`Channel($T)`; `recv → RecvResult($T)` tagged union built via
|
||||
@@ -96,9 +126,19 @@ ordering; `RecvResult` exercises the metatype primitives.
|
||||
- C.1 **M:N** — work-stealing (thread-safe steal queues + migration); **pinning** API
|
||||
(`pin = .main | .any | .on(thread)`). M:N is **committed, not deferred** — just last.
|
||||
|
||||
**Gates:** data races aren't snapshottable → **stress harness** (run-N / TSan-style),
|
||||
*loudly* out of corpus scope (§10.2). **Named `context`-fiber-local + errno migration
|
||||
test** (M:1 can't exercise migration — §10.7).
|
||||
**Gates:** data races aren't snapshottable, but "out of corpus scope" is **not** "no
|
||||
plan" — Stream C is **blocked on a concrete, named stress harness landing FIRST** (a
|
||||
gating artifact carved into `PLAN-PARALLEL.md`, not a footnote):
|
||||
1. **Sanitizer build** — a `zig build`-integrated TSan (and ASan) variant of the
|
||||
concurrency corpus; CI runs `18xx`/parallel examples under it.
|
||||
2. **Run-N driver** — each parallel example executed N times (configurable, default
|
||||
≥100) with interleaving perturbation (randomized ready-queue / yield injection); any
|
||||
nondeterministic divergence or sanitizer report fails the build.
|
||||
3. **Coverage-bound `log()`** — the harness emits, loudly, exactly which guarantees it
|
||||
does and does NOT cover (per the REJECTED-PATTERNS rule against silent gaps).
|
||||
This harness is the **only** correctness story for N×(M:1)/M:N; C.0/C.1 do not start
|
||||
until it exists and is calibrated. Plus the **named `context`-fiber-local + errno
|
||||
migration test** (M:1 can't exercise migration — §10.7).
|
||||
|
||||
---
|
||||
|
||||
@@ -143,14 +183,20 @@ module hazard; S2 TLS + C-constructor JIT test per host OS (the exact prior-spik
|
||||
|
||||
## Cross-cutting (applies across streams)
|
||||
|
||||
- **Testing keystone:** the deterministic-sim `Io` (B1.4) must exist + be calibrated
|
||||
before *any* async test is trusted (§10.1).
|
||||
- **Top risks to watch (§8.1):** A2 context-switch correctness (B1.3), minted-enum →
|
||||
match codegen (de-risked, metatype stream), deterministic-`Io` oracle calibration,
|
||||
`context`-fiber-local/errno (C), S2 (E), C1 args-buffer layout (D).
|
||||
- **The compiler floor stays small, but deep:** atomics, `callconv(.naked)`, repointable-
|
||||
`context` codegen, `declare`/`define`/`type_info` (metatype stream), the S1 JIT spine.
|
||||
Everything else — schedulers, fibers, channels, the bundler — is sx lib.
|
||||
- **Testing keystone:** the deterministic-sim `Io` (B1.4) gates *scheduling* tests
|
||||
(§10.1); the **B1.3 switch-stress harness gates the context-switch** (the one piece
|
||||
the deterministic `Io` can't test). Both must exist + be calibrated before the async
|
||||
tests they gate are trusted.
|
||||
- **Top risks to watch (§8.1):** A2 context-switch correctness (B1.3 — gated by its own
|
||||
stress harness, not the deterministic `Io`), minted-enum → match codegen (de-risked,
|
||||
metatype stream), deterministic-`Io` oracle calibration, `context`-fiber-local/errno
|
||||
(C — gated by the named stress harness), S2 (E), C1 args-buffer layout (D).
|
||||
- **The compiler floor stays small, but deep — net-new pieces, grounded:** atomics
|
||||
(100% net-new, no scaffolding), making `abi(.pure)` actually naked (the enum variant
|
||||
exists but is inert today), per-fiber `context` root + push-stack storage (`context`
|
||||
is already an implicit param, NOT TLS — so this is smaller/different than "repointable
|
||||
codegen" implied), `declare`/`define`/`type_info` (metatype stream — **done**), the
|
||||
S1 JIT spine. Everything else — schedulers, fibers, channels, the bundler — is sx lib.
|
||||
|
||||
## Carving protocol
|
||||
|
||||
|
||||
Reference in New Issue
Block a user