111 lines
3.9 KiB
Markdown
111 lines
3.9 KiB
Markdown
# 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`.
|
|
|