FABRIC-3.10.8 MC-2: observers stay on core 0
The decision's observer pass runs only on core 0; a switch into an observer on any other core is refused and counted (a guard, 0 in every run). Probe posing as core 1: no observer chosen, switch refused 0 -> 1; as core 0 the same decision returns Hestia. 3-ISA acceptance clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3c07636ecd
commit
c8b754fd80
@@ -37,6 +37,7 @@
|
||||
#include "starkernel/percpu.h" /* FABRIC-3.10.8 MC-0a -- this core's current VM */
|
||||
#include "starkernel/spinlock.h" /* FABRIC-3.10.8 MC-0b -- no lock crosses a switch */
|
||||
#include "starkernel/smp.h" /* FABRIC-3.10.8 MC-1 -- sk_smp_report() */
|
||||
#include "log.h" /* FABRIC-3.10.8 MC-2 -- the refusal report */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Arch-specific (switch.S in each arch dir). sk_vm_switch_prime() builds
|
||||
@@ -59,6 +60,10 @@ extern uint64_t sk_vm_switch_prime(uint64_t stack_top, void *entry);
|
||||
* who most recently switched into it does. */
|
||||
static VM *g_switch_entry_vm;
|
||||
|
||||
/* FABRIC-3.10.8 MC-2: switches refused because they would have entered an
|
||||
* observer on a core other than core 0. A guard -- expected to stay 0. */
|
||||
static uint64_t g_observer_refusals, g_observer_refusals_reported;
|
||||
|
||||
/* FABRIC-3.md §XXVIII Stage 3 follow-on (2026-09-14): which VM is
|
||||
* currently running, from the switch mechanism's own point of view --
|
||||
* independent of vm_log_attributed_vm() (vm_core.c), which is scoped to
|
||||
@@ -233,6 +238,11 @@ void sk_vm_idle_point(int may_drain_self) {
|
||||
sk_lock_check_none_held("idle point");
|
||||
sk_lock_report();
|
||||
sk_smp_report(); /* FABRIC-3.10.8 MC-1: a parked core that woke */
|
||||
if (g_observer_refusals != g_observer_refusals_reported) { /* MC-2 */
|
||||
g_observer_refusals_reported = g_observer_refusals;
|
||||
log_message(LOG_ERROR, "SWITCH: observer refused off core 0 x%llu",
|
||||
(unsigned long long)g_observer_refusals);
|
||||
}
|
||||
|
||||
if (!self || self != (VM *)sk_get_mama_vm()) return;
|
||||
if (self->frames.count != 0) return; /* inside a word (KEY/EXPECT): not idle */
|
||||
@@ -267,12 +277,19 @@ int sk_vm_parked_idle(const VM *vm) {
|
||||
vm_uuid_equal(vm->frames.entries[0].vm_id, vm->stadium_vm_id);
|
||||
}
|
||||
|
||||
uint64_t sk_vm_switch_observer_refusals(void) { return g_observer_refusals; }
|
||||
|
||||
int sk_vm_context_switch(VM *from, VM *to) {
|
||||
uint64_t new_sp;
|
||||
|
||||
if (!from || !to || to->native_stack_top == 0) {
|
||||
return -1;
|
||||
}
|
||||
/* MC-2 (MC-R1): the observers run on core 0 only. */
|
||||
if (sk_percpu()->core_id != 0 && sk_vm_switch_signal_is_observer(to->stadium_vm_id)) {
|
||||
__atomic_add_fetch(&g_observer_refusals, 1, __ATOMIC_RELAXED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (to->native_stack_saved_sp == 0) {
|
||||
/* First-ever entry: synthesize the initial frame. */
|
||||
|
||||
Reference in New Issue
Block a user