Files

107 lines
4.0 KiB
Markdown
Raw Permalink 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.
# K06 — MemoryResource and FreeRtosAllocator<T>
## Position
- Series: FreeRTOS C++
- Lesson: L05, card K06
- Duration: 30 minutes
- Runtime: FreeRTOS `heap_4.c` plus a 256-byte `.bss` arena on Hazard3
- C++ mode: freestanding C++17, no exceptions, RTTI, vtables or hosted allocator
K05 selected and measured one kernel heap. K06 adds an explicit runtime
resource boundary so identical typed code can use either that heap or caller
owned static storage.
## Outcome
After 30 minutes the student can draw the three-word resource object, explain
why it is not virtual inheritance, implement overflow-safe `count*sizeof(T)`,
classify addresses by storage domain, and state the different release policies
of a general heap and monotonic arena.
## Lesson plan — 30 minutes
| Time | Mode | Evidence |
| --- | --- | --- |
| 05 | contract | draw context + allocate/deallocate functions |
| 510 | typed count | complete and justify the overflow guard |
| 1016 | two resources | allocate 16 `uint32_t` values from heap and arena |
| 1621 | address proof | classify `ucHeap` versus `.bss`; check alignment |
| 2126 | failure | overflow and capacity failures change no storage state |
| 2630 | release | compare heap free, arena no-op deallocate and reset |
## Runtime dispatch without vtable
```cpp
struct MemoryResource {
void* context;
void* (*allocate)(void*, size_t, size_t) noexcept;
void (*deallocate)(void*, void*, size_t, size_t) noexcept;
};
```
The provider owns state; the view stores a non-owning context. `HeapResource`
counts attempts and delegates to FreeRTOS. `StaticArenaResource` stores base,
capacity and current offset. The ELF must have no vtable/typeinfo.
## Typed overflow contract
For `T` and `count`:
```text
count == 0 -> nullptr
count > SIZE_MAX / sizeof(T) -> nullptr, resource not called
otherwise bytes=count*sizeof(T) -> resource.allocate(bytes, alignof(T))
```
The failure must not wrap to a small allocation. Both resource counters and
storage state are captured before and after the overflow request.
## Canonical experiment
```text
HeapResource --MemoryResource--> FreeRtosAllocator<uint32_t> -> 16 values
address inside ucHeap; deallocate -> baseline immediately
StaticArenaResource --MemoryResource--> same typed allocator -> 16 values
address inside g_static_arena_storage (.bss)
deallocate -> used remains 64
reset -> used becomes 0
```
Both addresses satisfy `address % alignof(uint32_t) == 0` and both buffers
produce the predicted sums.
## Stable evidence
| Evidence | Required relation |
| --- | --- |
| resource representation | context and function pointers are non-null; allocate functions differ |
| heap address | lies inside `ucHeap`, aligned for `uint32_t` |
| arena address | lies in global arena range, outside `ucHeap`, aligned |
| overflow | both return null before provider failure counters increase |
| capacity failure | heap available and arena used remain unchanged |
| heap policy | successful=1, failed=1, deallocations=1; final free=baseline |
| arena policy | successful=1, failed=1; used 64 after deallocate, 0 after reset |
## Main traps
1. Multiply only after the division guard; detecting overflow after wrapping is
too late.
2. A resource view does not own its context; provider lifetime must dominate.
3. Arena `deallocate` is not heap free. Reset invalidates all arena allocations
at once and therefore needs an external lifetime boundary.
4. An alignment greater than the provider guarantee must fail explicitly.
5. This fallible allocator is not ordinary `new` and is not advertised as a
complete hosted/STL allocator.
## Acceptance
- host ASan/UBSan test validates alignment, overflow and no-op/reset behavior;
- `MemoryResource` occupies three pointers and all resource classes are
non-polymorphic;
- ABI has no vtable, RTTI, unwind, dynamic initializer or global new/delete;
- Hazard3 proves two storage domains and identical 16-element operations;
- all failure and release relations pass at checkpoint 7.