Zephyr Time Slicing: Test Equal-Priority Fairness Without Assuming Equal CPU Time

Zephyr time slicing gives eligible ready threads of equal priority opportunities to run. It does not promise equal accumulated CPU time, equal completed work or equal response latency. Qualify the service requirement with ready/running/blocked traces, especially when threads block frequently or higher-priority work repeatedly interrupts them.

This guide targets Zephyr v3.7.0 on one CPU with ordinary preemptive threads, no meta-IRQ threads, CONFIG_SCHED_DEADLINE disabled and CONFIG_TIMESLICE_PER_THREAD disabled. SMP and per-thread slice overrides need separate analysis. The focus is timer-driven equal-priority service, not cooperative yield policy or the implementation of CPU-statistics collection.

Prove that the threads are actually eligible

The versioned scheduling guide explicitly distinguishes time-slice opportunities from equitable CPU-time accounting. Before interpreting a trace, verify the configuration and current thread state rather than assuming that equal configured priorities are sufficient.

The v3.7.0 kernel configuration defines a slice-size setting in milliseconds. A value of zero imposes no ordinary slice limit. Consequently, enabling CONFIG_TIMESLICING alone does not prove a nonzero slice is active. Record the effective size and any runtime change as well as the enable flag.

Check Ordinary slicing consequence Diagnostic evidence
Nonzero slice configured A slice-expiry opportunity can exist Effective configuration and runtime setting
Thread is preemptible Ordinary slicing can apply Thread class and scheduler-lock state
Priority is within the slicing range Higher-priority exempt threads are excluded Actual priority and configured ceiling
Peer of equal priority is ready Another peer can use the opportunity Ready-state trace, not thread existence alone
Per-thread overrides disabled This guide’s ordinary eligibility assumptions hold CONFIG_TIMESLICE_PER_THREAD is disabled

The tagged slicing implementation checks preemptibility, nonzero slice time, priority eligibility and runnable state for the ordinary path; it excludes idle. It also contains a per-thread override path, which is why that feature is explicitly outside this table.

Track slice resets instead of imagining a permanent quota

In the single-CPU scheduler source, selecting a different thread through the relevant cache-update path resets the incoming thread’s slice. The slicing code also resets its timer after expiry handling. This is not a ledger that preserves each thread’s unused entitlement across every blocking and preemption interval.

If A blocks and B becomes current, B begins under the reset behavior. When A later becomes ready, it does not receive a transferable credit equal to the CPU time it missed while blocked. Blocking time, ready waiting and actual execution are different quantities.

Qualitative equal-priority trace: A is selected with a fresh slice, A blocks, B is selected with a fresh slice, A becomes ready while B runs, and B's slice expiry gives ready A an opportunity. The drawing is not measured timing or accumulated CPU quota.
Qualitative sequence with only A and B competing at the same priority. Slice resets and readiness transitions do not establish equal accumulated CPU service.

Higher-priority activity and interrupts further separate elapsed time from useful thread execution. Do not convert the configured slice directly into a guaranteed wall-clock response bound. Include scheduler locking and other nonpreemptible intervals in the explanation of any missed opportunity.

Define fairness in terms the product can test

Choose the requirement before collecting numbers. For a background worker, it may be a maximum ready-to-run delay under a stated interference envelope. For a processing pipeline, it may be completed jobs or maximum item age. For two CPU-bound tasks, a service-share observation may be useful, but it still needs a defined window and workload.

Do not compare raw loop counters when one iteration performs different work in each task. Nor should a task blocked waiting for a device be expected to accumulate the same CPU time as a continuously ready peer. Equal priority says nothing about equal demand.

A useful trace record includes thread identity, ready transition, switch-in, switch-out, block reason, slice configuration epoch and completed-work marker. Keep interrupt intervals visible where the tracing method supports them. Record observer overhead and lost records so a missing switch is not automatically blamed on the scheduler.

Run a controlled qualification matrix

  1. Both peers continuously ready: use bounded comparable CPU work, ordinary eligible priorities and a nonzero slice. Verify opportunities to switch between peers.
  2. One peer frequently blocks: add a controlled wait to A. Separate A’s blocked intervals from periods when it was ready but not running.
  3. Higher-priority bursts: introduce bounded interference and trace incoming-thread slice resets. Check the application’s service bound rather than expecting the baseline pattern to remain unchanged.
  4. No ready peer: block B and verify that a slice boundary need not produce a useful context switch to another equal-priority worker.
  5. Eligibility controls: compare zero slice size, an exempt priority and scheduler-locked execution in an isolated test. Confirm that the diagnostic recognizes each reason ordinary slicing may not apply.

These are proposed target tests; no Zephyr runtime fairness measurements were performed for this article. Preserve the effective configuration, trace method and workload script. Do not publish synthetic timings as an observed scheduler result.

Hypothetical example: unequal shares without unfair scheduling

Imagine a hypothetical compressor and storage worker assigned equal preemptive priority. The compressor stays ready, while storage repeatedly blocks for device completion. A dashboard shows more accumulated CPU time for compression, and the team proposes shortening the slice to “equalize” them.

The first useful distinction is whether storage was blocked or ready during the apparent gap. If blocked, a shorter slice cannot make the device finish earlier. If ready, inspect slicing eligibility, interference and reset behavior, then test the actual ready-to-service requirement. The same percentage difference can therefore have different explanations.

Accept service evidence, not a symmetry assumption

Deliver the eligibility table for the actual build, a state-separated trace and the requirement each worker must satisfy. Report observed service distribution only when measured, with its window and workload. Retain counterexamples showing zero-size or exempt-priority behavior so configuration regressions are detectable.

If the product requires a stronger allocation or deadline guarantee than ordinary slicing supplies, redesign the workload admission or scheduling contract and validate it explicitly. Changing the slice may alter responsiveness and switching overhead, but neither equal percentages nor a particular throughput improvement should be promised without target evidence.

Similar Posts