ReviewOS

zig-utils/zig-js

Runtime: schedule runnable slots with bounded priorities

#984
Closed chris opened this 9 days ago ·
9 days ago

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.
9 days ago

Implemented in 7c23eb6 and pushed to main.

Runnable-slot wake order is now explicit and portable. The six typed resources are classified as safety (concurrent GC marker, execution watchdog), foreground (JavaScript Thread, test262 agent), or background (script/module Worker). Waiters use allocation-free intrusive FIFO queues with stack-owned conditions and a repeating 4:2:1 grant cycle. Empty classes are skipped, new arrivals cannot bypass queued work, and every continuously queued class receives bounded service.

The coordinator reserves the slot, transitions the selected resource to runnable, removes its waiter, and records the grant in one coherent mutation before signaling. Schema-v6 telemetry reports each class's weight, current/peak waiters, cumulative grants, and last FIFO ticket. The checked runtime inventory and audit enforce all six priority rulings.

Validation:

  • deterministic 14-waiter order: SSSSFFB SSSSFFB, FIFO IDs preserved within every class
  • full units: 2,504 passed, 1 skipped, 0 failed, 0 leaked (2,505 total)
  • focused normal scheduler integration: 5/5 passed, zero leaks
  • focused TSan scheduler integration: 5/5 passed, zero leaks
  • standalone normal and TSan coordinator suites: 7/7 each
  • deterministic threadfuzz: 40/40 programs, 0 failures
  • runtime-thread audit: 6 production call sites across 6 resource classes
  • C API audit: 117/117 declarations, 460 private profile exports
  • docs: 51 pages, manifest stable
  • exact-parent ReleaseFast diagnostic: 1.006 median paired lifecycle ratio over 11 interleaved samples; diagnostic only, not publication evidence

Test262 flips were not measured because the corpus is absent in this checkout.

Sign in to comment on this issue.