Skip to main content

Module concurrency

Module concurrency 

Source
Expand description

The concurrency-lowering knob for the C-family backends.

LOGOS’s deterministic concurrency (channels / tasks / Await the first of / virtual-time Sleep) needs a task to SUSPEND at a blocking op and RESUME later. There are two ways to lower that suspend, and — like the CUDA crate::codegen_cuda::CudaKnobs lattice — neither is strictly better, so it is a knob with a documented trade-off (ConcurrencyLowering::tradeoffs). Unlike most knobs, one end is capability-forced: a target with no ucontext/setjmp (a GPU kernel, WASM, bare metal) can ONLY do the stackless form. So the lattice point is chosen by ConcurrencyLowering::for_target: the best-general choice each target can express.

  • ConcurrencyLowering::Ucontext — stackful coroutines (getcontext/makecontext/swapcontext). A blocking op yields mid-loop / mid-nested-call and the native stack survives, so codegen is SIMPLE (emit native code + a logos_yield() at each blocking point) and straight-line code runs at native speed with arbitrary nesting. But it needs ucontext/setjmp (host, RISC-V under qemu, a Tensix baby core) and a full stack per task (~256 KB). This is the RISC-V tier’s approach today.
  • ConcurrencyLowering::Stackless — a state machine: each task body is transformed into a resumable switch over its blocking points, with live locals hoisted into a heap frame. UNIVERSAL (CUDA device, WASM, embedded — no OS/libc), a tiny per-task frame, cheap function-return yields, and it scales to many tasks. But codegen is COMPLEX (the async/await-style transform) and each resume pays a small switch-dispatch cost. This is what the CUDA tier requires.

Structs§

ConcurrencyTradeoff
One knob’s trade-off — the regime where the setting wins and where it loses (why it can’t be baked in unconditionally). Mirrors crate::codegen_cuda::KnobTradeoff but kept local so codegen_c does not depend on codegen_cuda.
SchedulerConfig
All scheduler knobs, bundled. Has a Default and fluent setters so it is easy to annotate while still having a sensible baseline.
SchedulerKnobs
The knobs that parameterize the emitted deterministic scheduler. This is the SAME SchedulerConfig the oracle runtime (logicaffeine_runtime) runs — the ready-queue policy (FIFO / LIFO / round-robin / seeded-random / priority), the clock (virtual Logical vs Wall), the default channel capacity, and the M:N workers count (1 = cooperative single core, N = work-stealing) — plus the seed that drives the seeded chooser for the random-choice points (TaskPick under Random, SelectWinner, TimerTieBreak). Emitting C straight from a SchedulerConfig guarantees the AOT scheduler’s knobs are ONE-TO-ONE with the oracle’s, so a program run at knobs on the VM and the same knobs in AOT-C agree.

Enums§

CTarget
A C-family lowering target, classified by whether it can express stackful coroutines. The concurrency knob is forced to ConcurrencyLowering::Stackless exactly when ucontext is absent.
ClockMode
How the scheduler’s clock advances.
ConcurrencyLowering
How the C-family backend lowers a task’s suspend/resume. One point in the (one-dimensional) knob lattice; pick with ConcurrencyLowering::for_target.
SchedulePolicy
The ready-task selection discipline. Determinism holds under every policy: Fifo/Lifo/RoundRobin/Priority are deterministic by construction, and Random resolves its pick through the seeded Chooser, so it is reproducible under a fixed seed.