Table of Contents

The tick and the quantum

A preemptive scheduler needs a way to take control back from a thread that does not give it up, and the usual way is a periodic timer interrupt, the tick. A timer is programmed to interrupt every few milliseconds, and each interrupt enters the kernel, which charges the running thread for the time and decides whether it has run long enough. The quantum, or time slice, is how long a thread may run before the scheduler considers another one. It is counted in ticks, so it can be one tick or several but never less than one: the scheduler cannot preempt more finely than the timer interrupts.

A timer can also be programmed one interrupt at a time. A one-shot timer is set for the moment the next decision is due, the end of the current slice or the nearest deadline, and the kernel programs it again from each interrupt. Kernels that work this way, often called tickless, avoid waking an idle CPU for nothing and can meet a deadline that does not fall on a tick, at the cost of reprogramming the timer for every decision.

The trap is accounting by tick. Charging the running thread one period per interrupt is sampling, not measurement: a thread that runs between two ticks and blocks before the next is charged nothing, and the thread that happens to be running when the tick lands is charged for the whole period. Over many ticks the samples average out for threads that run long, but a thread that wakes, works briefly and sleeps again can stay almost free. A tick that arrives late is charged as if it were on time, too, unless the kernel reads a clock.

In Cosmos the boot path arms the scheduler tick at SchedulerManager.DefaultQuantumNs, 10 ms. On x64 it comes from the local APIC timer running periodic; on ARM64 the Generic Timer is re-armed from each interrupt, a one-shot used as a periodic tick. Each tick first readies the sleepers whose deadline has passed, then calls the policy's OnTick with elapsedNs, the configured period rather than a measurement. Charging it to SchedulerThread.TotalRuntime is the policy's job, a quantum longer than one tick is a counter the policy decrements across ticks, and returning true reschedules before the interrupt returns. SchedulerDiagnostics.TickPeriodNs reports the period the timer last passed in, which follows a retune where DefaultQuantumNs does not, and nothing yet lets a policy program the next interrupt itself. See Timer sources, The tick and Real-time notes.