feat: add lab-rv32i-freertos-heap-models card
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# K05 — FreeRTOS C++ heap bridge, heap models and `HeapStats`
|
||||
|
||||
K05 separates three questions that are often collapsed into one:
|
||||
|
||||
1. Which FreeRTOS heap policy fits the deployment (`heap_1`…`heap_5`)?
|
||||
2. How do all ordinary C++ allocation/deallocation forms enter one selected
|
||||
FreeRTOS heap domain?
|
||||
3. What can current free bytes, largest block and minimum-ever free bytes
|
||||
actually prove?
|
||||
|
||||
The Hazard3 executable uses the real upstream `heap_4.c`. It allocates three
|
||||
C++ arrays, frees the first and third, and obtains two free regions separated
|
||||
by the still-live middle array. A request one byte larger than the largest
|
||||
region fails even though the *sum* of free bytes is larger than the request.
|
||||
After the middle array is released, `heap_4` coalesces adjacent blocks and the
|
||||
same request succeeds.
|
||||
|
||||
## Heap policy map
|
||||
|
||||
| Scheme | Release | Coalescence | Memory source / typical fit |
|
||||
| --- | --- | --- | --- |
|
||||
| `heap_1` | no | not applicable | one monotonic region; allocate during startup and never free |
|
||||
| `heap_2` | yes | no | legacy/simple reuse with fragmentation risk |
|
||||
| `heap_3` | libc `free` | delegated | compiler/linker `malloc` heap; requires that runtime contract |
|
||||
| `heap_4` | yes | adjacent blocks | one FreeRTOS region; general single-region teaching target |
|
||||
| `heap_5` | yes | within regions | multiple address-ordered, possibly non-contiguous regions |
|
||||
|
||||
Only one implementation supplies `pvPortMalloc()`/`vPortFree()` in an image.
|
||||
The C++ bridge does not make the five policies run simultaneously.
|
||||
|
||||
## C++ surface
|
||||
|
||||
[`HeapStats`](include/freertos/heap_stats.hpp) is a value snapshot of
|
||||
`HeapStats_t`. [`HeapWatermark`](include/freertos/heap_stats.hpp) interprets
|
||||
current and peak consumption relative to a captured baseline. The bridge in
|
||||
[`cpp_heap.cpp`](src/common/cpp_heap.cpp) supplies all six required paths:
|
||||
|
||||
- scalar and array `operator new`;
|
||||
- scalar and array unsized `operator delete`;
|
||||
- scalar and array sized `operator delete`.
|
||||
|
||||
This no-exceptions profile gives ordinary `new` a fail-fast contract. The
|
||||
controlled failure experiment therefore calls `pvPortMalloc()` directly with
|
||||
the malloc-failed hook disabled; it is a deliberately fallible probe, not a
|
||||
claim that ordinary `new` returns `nullptr`.
|
||||
|
||||
## Seven checkpoints
|
||||
|
||||
| Point | Required evidence |
|
||||
| --- | --- |
|
||||
| 1 | baseline: one free block and current free bytes recorded |
|
||||
| 2 | three C++ allocations; payload intact; current free decreases |
|
||||
| 3 | first and third freed; two free blocks; total exceeds largest |
|
||||
| 4 | request=`largest+1` fails; successful allocation count unchanged |
|
||||
| 5 | middle freed; one coalesced block; current free equals baseline |
|
||||
| 6 | identical request now succeeds and lies in `ucHeap` |
|
||||
| 7 | retry freed; baseline recovered; minimum-ever still records history |
|
||||
|
||||
On the checked RV32I build the core fragmentation evidence is:
|
||||
|
||||
```text
|
||||
available = 0x2fe0 (12256)
|
||||
largest = 0x27d0 (10192)
|
||||
request = 0x27d1 (10193)
|
||||
blocks = 2
|
||||
peak used = 0x27f0 (10224)
|
||||
```
|
||||
|
||||
## Build and verify
|
||||
|
||||
```sh
|
||||
make check
|
||||
```
|
||||
|
||||
Expected summary:
|
||||
|
||||
```text
|
||||
PASS host: HeapStats mapping and watermark history
|
||||
PASS ABI: complete new/delete bridge and zero hosted C++ runtime
|
||||
PASS task01: heap_4 fragmentation + coalescence + history
|
||||
```
|
||||
|
||||
## Debug
|
||||
|
||||
```gdb
|
||||
b heap_models_debug_checkpoint
|
||||
p g_last_checkpoint
|
||||
p g_baseline_stats
|
||||
p g_after_alloc_stats
|
||||
p g_fragmented_stats
|
||||
p g_after_failure_stats
|
||||
p g_coalesced_stats
|
||||
p g_after_retry_stats
|
||||
p g_final_stats
|
||||
p g_failure_request
|
||||
p g_cpp_allocation_addresses
|
||||
p g_cpp_deallocation_addresses
|
||||
p g_peak_bytes_used
|
||||
p g_heap_models_pass
|
||||
```
|
||||
|
||||
## Scope boundary
|
||||
|
||||
`available_bytes` is a sum, not a promise of one contiguous payload. The
|
||||
largest free block is allocator metadata-level evidence and an allocation also
|
||||
needs its aligned header. K05 compares policy and measures one selected heap;
|
||||
runtime-selected resources and typed allocators are deferred to K06.
|
||||
|
||||
Render the printable worksheet with `make pdf`.
|
||||
|
||||
Reference in New Issue
Block a user