Files

4.5 KiB
Raw Permalink Blame History

K04 — Scheduler states, priorities, time slicing and typed ticks

Position in the series

  • Series: FreeRTOS C++
  • Lesson: L03, card K04
  • Duration: 30 minutes
  • Executables: exactly one
  • Kernel: unchanged FreeRTOS V11.3.0 in C
  • C++ mode: freestanding C++17, no exceptions, RTTI or hosted libstdc++
  • New C++ surface: Ticks, TickPoint, non-owning TaskRef

K02 introduced task entry and lifecycle, while K03 established ownership and RAII for a heap buffer. K04 deliberately does not build a large facade. It first exposes the scheduler's raw evidence and adds only types that prevent a duration, a tick point and an owning task object from being confused.

Outcome

After 30 minutes the student can predict and verify READY, RUNNING, BLOCKED and DELETED; distinguish a relative delay from a periodic wake reference; explain time slicing for equal priorities; and use the order BEFORE -> HIGH -> AFTER as proof of immediate priority preemption.

Lesson plan — 30 minutes

Time Mode Required evidence
04 prediction fill the first state/priority table without running code
48 typed time distinguish Ticks from TickPoint; no assumption that tick means ms
813 time slicing obtain A,B,A or B,A,B at equal priority 2
1319 blocked state show A=eBlocked, B=eRunning, elapsed exactly 3 ticks
1925 priority change show B at priority 3 and marker order 1,2,3
2530 interpretation compare relative/periodic delay, state limits and stale TaskRef

Canonical experiment

scheduler starts
  -> startup probe: A READY, B READY
  -> equal priority 2: A/B alternate on tick boundaries
  -> A calls vTaskDelay(3)
  -> A BLOCKED; B RUNNING
  -> at start+3 A becomes READY and then RUNNING
  -> A writes BEFORE=1 and raises B to priority 3
  -> B preempts, writes HIGH=2, lowers itself to priority 2
  -> A resumes inside/after vTaskPrioritySet and writes AFTER=3
  -> workers delete themselves; verifier writes terminal snapshot and PASS

The test accepts either initial equal-priority order. It requires the alternating relation first == third && first != second.

Stable evidence contract

Evidence Required relation
g_alternating_tasks[0..2] A,B,A or B,A,B
delay snapshot A=eBlocked, B=eRunning
delay timestamps end - start == 3, observation lies before end
priority snapshot A=eReady, B=eRunning, B priority 3
g_priority_order exactly 1,2,3
terminal snapshot A/B recorded as eDeleted, handles no longer queried
g_scheduler_states_pass 1

Prediction table

The student completes state and priority before inspecting the executable:

Event A state / priority B state / priority Current task Why?
startup probe
A before delay
B while A delays
A after 3 ticks
before raise
B at p=3
after API returns
verifier

Typed wrapper boundary

freertos::Ticks duration{3};
const auto start = freertos::TickPoint::now();
vTaskDelay(duration.count());
const auto elapsed = freertos::TickPoint::now() - start;

freertos::TaskRef peer{handle}; // no ownership
peer.set_priority(3);

TaskRef is the size of one native handle and has no virtual dispatch. It must not be used after the task is deleted. K04 uses raw scheduling calls on purpose; a broad Scheduler facade is deferred until K09.

Misconceptions to surface

  1. Highest priority does not mean “always running”: a high-priority task can be blocked and therefore ineligible.
  2. vTaskDelay(3) does not promise three milliseconds unless the configured tick rate makes that conversion true.
  3. vTaskDelay is relative; repeated work plus relative delays can drift. xTaskDelayUntil advances a periodic reference.
  4. Equal priority does not establish a fixed first task; verify alternation, not a guessed first ID.
  5. A handle is not ownership. After deletion, TaskRef can dangle.

Acceptance

  • host test proves typed tick arithmetic, wrap-around and one-handle TaskRef;
  • ELF contains no RTTI, vtable, exception/unwind or hosted C++ dependency;
  • Hazard3 proves a three-entry alternating trace;
  • the blocked snapshot and exactly-three-tick delay pass;
  • priority markers are exactly 1,2,3 and B is priority 3 at marker 2;
  • all eight snapshots match the intended state transition sequence;
  • student explains why the startup snapshot is taken after scheduler start.