Parent: #502 Depends on: #982, #983
Goal
Replace OS-accidental runnable-slot wake order with an explicit, starvation-bounded process scheduler for the six typed runtime thread classes.
Current behavior
All slot waiters park on one condition. A release signals one unspecified waiter, so GC safety work, termination watchdogs, foreground shared-realm mutators, and isolated Workers have no observable ordering contract. Repeated higher-value work also has no fairness bound.
Scope
- Classify typed resources as:
- safety: concurrent GC marker, execution watchdog;
- foreground: JavaScript Thread, test262 agent;
- background: script Worker, module Worker.
- Replace the shared condition race with allocation-free intrusive waiter queues. Each waiter owns a stack-local condition and a monotonic ticket; the coordinator grants a slot before signaling it.
- Preserve FIFO order within each priority class.
- Use a documented weighted round-robin cycle of 4 safety, 2 foreground, and 1 background grant. Empty classes are skipped, so capacity is never intentionally idled and a continuously queued background class receives a bounded grant under sustained higher-priority pressure.
- Queue new entrants behind existing waiters even when a slot becomes available, preventing late arrivals from bypassing queued work.
- Keep
active_slots = sum(resource.runnable)exact by publishing the slot and resource transition in the same mutation before wakeup. - Extend machine-readable telemetry with per-priority current/peak waiters, cumulative grants, and configured weights; export the priority type through the public Zig module.
- Add deterministic mixed-class tests that prove the weighted sequence and FIFO order at one slot, plus real JavaScript Thread/Worker handoff coverage under normal and TSan.
- Update the resource coordination documentation and generated docs manifest.
Non-goals
OS thread priority/affinity, dynamic priority donation, JIT/Wasm compilation queues, cancellation, and memory-pressure feedback remain separate #502 work.
Acceptance
- With all classes continuously queued, grants follow the exact 4:2:1 cycle and FIFO within a class.
- Empty classes do not waste slots; no queued class starves.
- New arrivals cannot bypass queued waiters.
- Lowering limits keeps already granted/runnable work grandfathered; raising limits dispatches exactly the newly available capacity.
- Snapshot invariants remain coherent under concurrent queueing and wakeup.
- Focused normal/TSan scheduler tests, full units, runtime-thread audit, and deterministic threadfuzz pass.