86 lines
2.7 KiB
Markdown
86 lines
2.7 KiB
Markdown
# K08 — dynamic/static task storage, deletion and lifetime
|
|
|
|
K08 gives identical worker behavior two storage policies:
|
|
|
|
- `DynamicTask` calls `xTaskCreate`; FreeRTOS allocates TCB and stack from
|
|
`heap_4` and the idle task later reclaims them after self-deletion;
|
|
- `StaticTask` calls `xTaskCreateStatic` with caller-owned `StaticTask_t` and
|
|
`StackType_t[]` located in `.bss`; task deletion never transfers ownership of
|
|
those buffers to the kernel.
|
|
|
|
Both wrappers remain non-copyable, non-movable and non-virtual. The static
|
|
storage is a separate `StaticTaskStorage<N>` object so its TCB/stack are visibly
|
|
caller supplied and their lifetime is independent from the wrapper's handle.
|
|
|
|
## Measured Hazard3 result
|
|
|
|
```text
|
|
dynamic heap cost = 0x470 = 1136 bytes
|
|
free before idle cleanup = 0x3b80
|
|
free after idle cleanup = 0x3ff0 (baseline)
|
|
static stack words = 0x100 = 256
|
|
static stack bytes = 0x400 = 1024
|
|
```
|
|
|
|
The dynamic worker sets `completed` and clears its wrapper handle before
|
|
`vTaskDelete(nullptr)`, but its kernel storage is only placed on the termination
|
|
list at that point. A static verifier first captures the reduced heap, blocks
|
|
for two ticks to let idle run, then observes full recovery.
|
|
|
|
## Evidence
|
|
|
|
| Stage | Heap relation |
|
|
| --- | --- |
|
|
| baseline | initialized `heap_4`, no worker kernel object |
|
|
| dynamic start | free decreases by 1136 B |
|
|
| static start | free unchanged from dynamic-start value |
|
|
| static verifier create | free unchanged again |
|
|
| workers completed/self-deleted | dynamic 1136 B still not reclaimed |
|
|
| verifier blocks, idle cleans | free increases by 1136 B to baseline |
|
|
|
|
Addresses prove dynamic TCB/stack lie in `ucHeap`, while the static TCB and
|
|
stack equal the caller storage addresses in `.bss`. Both workers compute
|
|
500500.
|
|
|
|
## Build
|
|
|
|
```sh
|
|
make check
|
|
```
|
|
|
|
Expected:
|
|
|
|
```text
|
|
PASS host: dynamic/static policies, stable caller storage and units
|
|
PASS ABI: dynamic/static trampolines; caller storage in .bss; no vtable
|
|
PASS task01: dynamic/static task storage + idle cleanup
|
|
```
|
|
|
|
## Debug
|
|
|
|
```gdb
|
|
b task_storage_debug_checkpoint
|
|
p g_heap_baseline
|
|
p g_heap_after_dynamic_start
|
|
p g_heap_after_static_start
|
|
p g_heap_before_idle_cleanup
|
|
p g_heap_after_idle_cleanup
|
|
p/x g_dynamic_tcb
|
|
p/x g_dynamic_stack_low
|
|
p/x g_static_tcb
|
|
p/x g_static_tcb_storage
|
|
p/x g_static_stack_low
|
|
p/x g_static_stack_storage
|
|
p g_static_stack_words
|
|
p g_static_stack_bytes
|
|
p g_task_storage_pass
|
|
```
|
|
|
|
## Scope boundary
|
|
|
|
Task deletion does not safely unwind arbitrary application resources on its
|
|
stack. The workers arrange normal member completion before self-deletion. Static
|
|
storage must outlive the task and must not be reused merely because a stop was
|
|
requested; completion/deletion must be established first.
|
|
|