Files
lab-rv32i-freertos-schedule…/doc/card-plan.md
T

119 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```text
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
```cpp
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.