threads(M8): the task reaper — reclaim dead tasks' kernel stacks
A dead task's kernel stack was leaked (no reaper), so every process/thread death bled kernel memory. Now exit()/exitUserLocked record the dying task in a per-core reap_after_switch slot and switch away; the task that resumes on that core frees the stack in switchTo's tail (on its own stack, lock still held so the slot can't be reused). reapKillPendingLocked drains the slot on the timer tick as a safety net for the fresh-task case (a fresh task enters via the trampoline, bypassing switchTo's tail). A task killed while not running is freed directly in destroyTaskLocked. live_stack_bytes is the observable. Fixed a migration bug this exposed: the post-switchContext reap read the pc parameter, but a migrated task carries a stale pc in its saved switchTo frame -> it freed the wrong core's pending stack (a #GP under SMP). Re-fetch thisCpu() after the switch. Gate task-reap PASS (5x isolated, 2x in the 24-case batch); full guardrail 24/24 incl. fault-recovery/supervision/process-kill/smp/affinity; build + host green.
This commit is contained in:
@@ -347,6 +347,14 @@ CASES = [
|
||||
"timeout": 60,
|
||||
"expect": r"DANOS-TEST-RESULT: PASS",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||
|
||||
# docs/threading-plan.md M8: the task reaper — spawn+kill many processes; total kernel
|
||||
# stack bytes return to baseline (every dead task's stack reclaimed, no leak).
|
||||
{"name": "task-reap",
|
||||
"smp": 4,
|
||||
"timeout": 60,
|
||||
"expect": r"DANOS-TEST-RESULT: PASS",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||
# Process arguments: argv arrives on the SysV entry stack (argv[0] = the spawned
|
||||
# name, argv[1..] = the system_spawn argument blob) and echoes back intact.
|
||||
{"name": "args",
|
||||
|
||||
Reference in New Issue
Block a user