Stage D: parked-idle VMs are killable, KILL unregisters; fix uninitialized pending_reap (FABRIC-3.8 §3.5, G6)
sk_vm_parked_idle(): saved context + exactly its own IDLE frame. capsule_vm_kill_refusal() is the single kill rule, shared by capsule_vm_kill() and the KILL word: refuse SWITCHED_OUT mid-task, parked with mail pending, or the VM running; allow parked-idle. capsule_vm_kill() now unregisters the switch slot (G6). Finding fixed: vm_registry_alloc() never initialized pending_reap (kmalloc does not zero); C-b's reap_pending walks every participant, so garbage reaped a healthy VM (seen live before any KILL). Now zeroed at alloc. Probe (reverted): baseline KILL refused, slots 3->4->4 (FAIL, proves G6); with Stage D dprobe parked idle, KILL dead, slots 3->4->3, PASS on amd64/ aarch64/riscv64. Acceptance: dict_hash unchanged, relay 3, idle growth 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
06bcab504d
commit
604ad7aadc
@@ -236,6 +236,19 @@ void capsule_vm_registry_init(void *mama_vm_ptr);
|
||||
*/
|
||||
int capsule_vm_kill(const char *name);
|
||||
|
||||
/**
|
||||
* capsule_vm_kill_refusal - FABRIC-3.8.md §3.5 (Stage D, 2026-09-23): the
|
||||
* one place the "may this VM be killed right now" rule lives, shared by
|
||||
* capsule_vm_kill() and the KILL word (which must decide before its own
|
||||
* heat retire / active-VM cleanup runs). Returns NULL if killable, else a
|
||||
* " refused -- ..." reason suitable to print after "KILL: <name>". Refused:
|
||||
* a SWITCHED_OUT VM parked mid-task (a live frame awaits resuming) or
|
||||
* parked with mail still pending, and the VM physically running. Allowed:
|
||||
* LIVE VMs as before, and SWITCHED_OUT VMs parked idle at their own
|
||||
* trampoline (sk_vm_parked_idle()) with an empty queue.
|
||||
*/
|
||||
const char *capsule_vm_kill_refusal(const VMRegistryEntry *entry);
|
||||
|
||||
/**
|
||||
* capsule_vm_registry_get - Get VM registry entry by ID
|
||||
*
|
||||
|
||||
@@ -68,6 +68,14 @@ void sk_vm_switch_checkpoint(struct VM *vm);
|
||||
* switches to the coolest VM with work, if any. */
|
||||
void sk_vm_idle_point(void);
|
||||
|
||||
/* FABRIC-3.8.md §3.5 (Stage D): 1 if `vm` is parked at its own trampoline
|
||||
* with nothing in progress -- its frame stack holds exactly one frame, its
|
||||
* own VM_FRAME_IDLE. Its saved context is the bare trampoline loop; no
|
||||
* payload, no borrowed frame, nothing that would ever need resuming. This
|
||||
* is what makes a SWITCHED_OUT VM killable. (Hera parked at her idle point
|
||||
* also has one IDLE frame, but she can never be killed anyway.) */
|
||||
int sk_vm_parked_idle(const struct VM *vm);
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
#endif /* STARKERNEL_VM_SWITCH_H */
|
||||
|
||||
Reference in New Issue
Block a user