DocsDecisions

ADR-0008: Job system scheduling in Mojo, threads and parking from the shim

Status: Accepted, 2026-11-08

Context #

The brief requires a work-stealing job system written in Mojo that runs everything except SDL and presentation. Mojo 1.2.0's standard library exposes parallelism_level() and parallelize() but no public API to create OS threads or to block and wake a thread; its async runtime is documented as private and unfinished (std.runtime). Spike 4 showed that Mojo abi("C") functions run correctly when a native thread calls them.

Decision #

  • Scheduling is Mojo (cinder/core/jobs.mojo): a fixed-capacity job table, one Chase-Lev deque of job indices per thread (deque 0 is the main thread's), work stealing by idle workers, completion counters (Counter, an Atomic[Int32]), and wait that helps execute jobs instead of blocking. All synchronisation uses std.atomic.Atomic with explicit Ordering arguments.
  • Threads and parking are C (native/src/threads.c): cn_thread_create/join/yield, cn_cpu_count, and a counting semaphore (sem_t on Linux, dispatch_semaphore_t on macOS). Each worker thread's entry point is the Mojo function _worker_entry declared abi("C"), given a pointer to a heap-allocated WorkerContext that outlives the thread.
  • No allocation in steady state: the job table, deques and worker contexts are allocated at construction. submit reports saturation with False and the caller runs the job inline; reset recycles the table at a point where no job is in flight (frame start).

Consequences #

  • The threading model is documented in docs/THREADING.md; the shim's thread code is covered by the ASan/UBSan CTest build and the Mojo tests run against both shim builds.
  • Memory orderings are conservative (SEQUENTIAL on the deque's pop/steal races, acquire/release elsewhere). Relaxing them is a measured optimisation for Phase 8, not a correctness change.
  • Job functions are thin function pointers with an untyped data pointer; typed, closure-like submission helpers are layered on top in the ECS scheduler (Phase 5) where the job graph is known.
View as MarkdownSource: docs/adr/0008-job-system-threads.md