Stage 3 follow-on: message-arrival eligibility hook + trampoline-blind switch-storm fix (FABRIC-3.md §XXVIII.2)
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run

Implements the message-arrival eligibility signal FABRIC-3.md §XXVIII.1 left
open (has_work per-slot flag, set via new SWITCH-MARK-WORK primitive from
MSG-SEND) so an idle VM never becomes a switch target purely by waiting out
the readiness threshold.

Also root-causes and fixes a second, independent switch-storm: the tick's
"who is current" check used vm_log_attributed_vm(), which can't see a VM
parked in switch.c's own raw trampoline. Replaced with a dedicated
g_switch_current_vm tracked by the switch mechanism itself, and moved
target-slot eligibility reset to the switch decision point instead of
relying on ISR polling to observe a window that can be only a few
instructions wide.

Verified live on all 3 architectures: clean boot to zuse@Hera] ok>, live
cross-VM message dispatch, and (since a quiet log looks identical to a
livelocked storm once the DoE probe is gone) confirmed genuine REPL
liveness via QMP send-key + screendump on aarch64/riscv64, not log
inspection alone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
Robert Allan James
2026-09-14 17:39:20 -04:00
co-authored by Claude Sonnet 5
parent 862d7d9c48
commit 66beae7fd4
29 changed files with 121129 additions and 338 deletions
+15 -2
View File
@@ -78,8 +78,21 @@ VMUuid sk_vm_switch_signal_take_pending(void);
/* Call once, from the same checkpoint, immediately after a switch
* sk_vm_switch_signal_take_pending() requested actually executes (not if
* the target turned out invalid/self) -- feeds the DoE CSV counters
* below. */
void sk_vm_switch_signal_note_switch_performed(void);
* below. Also resets `target_id`'s own readiness/has_work directly
* (Stage 3 follow-on correction, 2026-09-14) -- see the .c file's own doc
* comment on why this can't be left to tick()'s current-slot polling. */
void sk_vm_switch_signal_note_switch_performed(VMUuid target_id);
/* Message-arrival eligibility hook (FABRIC-3.md §XXVIII Stage 3 follow-on,
* 2026-09-14): mark that VM `vm_id` was just sent a message (the FORTH-side
* MSG-SEND hook in capsules/common/messaging.4th calls this via the new
* SWITCH-MARK-WORK primitive, mainline, single-writer). Consulted by
* sk_vm_switch_signal_tick()'s own readiness->pending decision so a VM
* with nothing recently sent to it never becomes a switch target purely by
* sitting idle long enough -- closes the wasteful (but, since the Stage 3
* stack-ownership fix, no longer corrupting) trampoline-bounce cycle for
* an idle participant. No-op for an unregistered vm_id. */
void sk_vm_switch_signal_mark_work(VMUuid vm_id);
/* DoE CSV read-only exposure (FABRIC-3.md §XXVIII Stage 3 follow-on,
* 2026-09-13) -- all of this state already existed for the switch
+9
View File
@@ -46,6 +46,15 @@ struct VM;
int sk_vm_context_switch(struct VM *from, struct VM *to);
/* FABRIC-3.md §XXVIII Stage 3 follow-on (2026-09-14): which VM is
* currently physically running, tracked by the switch mechanism itself --
* see switch.c's own doc comment on g_switch_current_vm for why this
* exists instead of reusing vm_log_attributed_vm(). sk_vm_switch_set_
* current() seeds the initial value (whoever is running before any
* switch has ever happened) -- call once, at Stage 3 registration time. */
struct VM *sk_vm_switch_current_vm(void);
void sk_vm_switch_set_current(struct VM *vm);
#endif /* __STARKERNEL__ */
#endif /* STARKERNEL_VM_SWITCH_H */