4.5 KiB
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-owningTaskRef
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 |
|---|---|---|
| 0–4 | prediction | fill the first state/priority table without running code |
| 4–8 | typed time | distinguish Ticks from TickPoint; no assumption that tick means ms |
| 8–13 | time slicing | obtain A,B,A or B,A,B at equal priority 2 |
| 13–19 | blocked state | show A=eBlocked, B=eRunning, elapsed exactly 3 ticks |
| 19–25 | priority change | show B at priority 3 and marker order 1,2,3 |
| 25–30 | 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
- Highest priority does not mean “always running”: a high-priority task can be blocked and therefore ineligible.
vTaskDelay(3)does not promise three milliseconds unless the configured tick rate makes that conversion true.vTaskDelayis relative; repeated work plus relative delays can drift.xTaskDelayUntiladvances a periodic reference.- Equal priority does not establish a fixed first task; verify alternation, not a guessed first ID.
- A handle is not ownership. After deletion,
TaskRefcan 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,3and 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.