Stage I: strip dead code -- pump drain loop, SWITCH-MARK-WORK, global interpret depth, native_switch_back_to (FABRIC-3.8 §4 row I)
Each shown dead three ways (FABRIC-3.5 §XXII): the pump loop by its condition, by construction (birth cap == switch table capacity, every birth registers) and at run time (probe silent through boot, G interleave, an 8-worker DoE trial and the relay); SWITCH-MARK-WORK by callers, capsules (source and baked), experiments/tools/logs; the depth counter and back_to field by having no readers. Kept: Hera's own pump drain (last timer-paced delivery, Hera only) and the always-0 readiness CSV columns (a DoE schema call). Acceptance on amd64/ aarch64/riscv64: G interleave unchanged, cfg-0 trial fail=0 2/2 dead, relay 3, idle growth 0; dict_hash set changed by the removed word (word_count 531) and identical across ISAs. FABRIC-3.8 stages A-I done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f152a91099
commit
dd23c3aa45
@@ -333,15 +333,6 @@ void sk_vm_switch_signal_note_switch_performed(VMUuid target_id) {
|
||||
g_beats_since_switch = 0;
|
||||
}
|
||||
|
||||
void sk_vm_switch_signal_mark_work(VMUuid vm_id) {
|
||||
/* Stage C-b: eligibility is read from the kernel-Hermes queue itself,
|
||||
* so there is no has_work flag to set. Kept (SWITCH-MARK-WORK still
|
||||
* calls it) as a "something changed, decide again" hint; Stage I
|
||||
* strips it if nothing calls it. */
|
||||
(void)vm_id;
|
||||
g_decision_due = 1;
|
||||
}
|
||||
|
||||
uint64_t sk_vm_switch_signal_switch_count(void) {
|
||||
return g_switch_count;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#include "starkernel/capsule_vm_physics.h"
|
||||
#include "starkernel/vm/vm_internal.h"
|
||||
#include "starkernel/vm/stadium.h" /* item 4.2 -- STADIUM-* words */
|
||||
#include "starkernel/capsule_vm_switch_signal.h" /* FABRIC-3.md §XXVIII Stage 3 follow-on -- SWITCH-MARK-WORK */
|
||||
#include "starkernel/vm/stadium_words.h" /* item 4.2 -- stadium_words_resident_heat() */
|
||||
#include "starkernel/repl.h"
|
||||
#include "starkernel/capsule_generated.h"
|
||||
@@ -832,47 +831,12 @@ static void mama_word_vm_exec(VM *vm)
|
||||
/* Stack clean on exit */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SWITCH-MARK-WORK ( name-caddr name-u -- )
|
||||
* FABRIC-3.md §XXVIII Stage 3 follow-on (2026-09-14): message-arrival
|
||||
* eligibility hook. Called from MSG-SEND (capsules/common/messaging.4th)
|
||||
* every time a message is sent to a VM, so the Stage 3 switch signal can
|
||||
* tell "has recently been sent something" apart from "has just been idle
|
||||
* long enough" before ever selecting it as a switch target. Silently
|
||||
* ignores a malformed or unknown name -- this fires on the hot path of
|
||||
* every message send, not a user-facing command, so it must never error
|
||||
* or spam the console.
|
||||
*/
|
||||
static void mama_word_switch_mark_work(VM *vm)
|
||||
{
|
||||
char name[VM_NAME_MAX];
|
||||
cell_t u, caddr;
|
||||
uint32_t i;
|
||||
VMRegistryEntry entry;
|
||||
|
||||
/* FABRIC-3.md §XXXII.6, 2026-09-15: this guard used to set vm->error on
|
||||
* underflow, contradicting this function's own doc comment above ("must
|
||||
* never error or spam the console") -- flagged as a special case in
|
||||
* §XXXII.3's triage, not just a missing diagnostic. Silently ignored,
|
||||
* matching every other malformed-input case in this same function. */
|
||||
if (vm->dsp < 1) return;
|
||||
|
||||
u = vm_pop(vm);
|
||||
caddr = vm_pop(vm);
|
||||
|
||||
if (u <= 0 || (uint32_t)u >= VM_NAME_MAX) return;
|
||||
|
||||
{
|
||||
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
|
||||
if (!p) return;
|
||||
for (i = 0; i < (uint32_t)u; i++) name[i] = (char)p[i];
|
||||
name[u] = '\0';
|
||||
}
|
||||
|
||||
if (capsule_vm_find_by_name_nocase(name, &entry) == 0) {
|
||||
sk_vm_switch_signal_mark_work(entry.vm_id);
|
||||
}
|
||||
}
|
||||
/* SWITCH-MARK-WORK (FABRIC-3.md §XXVIII Stage 3 follow-on) was removed at
|
||||
* FABRIC-3.8.md Stage I (2026-09-24). Its only caller, MSG-SEND in
|
||||
* capsules/common/messaging.4th, was deleted in FABRIC-3.6.md Phase 4; since
|
||||
* Stage C-b a VM's eligibility is its kernel-Hermes queue itself, so there
|
||||
* is nothing left for it to mark. No capsule (source or baked), experiment,
|
||||
* tool or committed log invokes it. */
|
||||
|
||||
/**
|
||||
* @brief VM-CALL ( cmd-caddr cmd-u vm-name-caddr vm-name-u -- n )
|
||||
@@ -2393,7 +2357,6 @@ void register_mama_forth_words(VM *vm)
|
||||
register_word(vm, "VM-PHYSICS-STATUS", mama_word_vm_physics_status);
|
||||
register_word(vm, "VM-STEP", mama_word_vm_step);
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "SWITCH-MARK-WORK", mama_word_switch_mark_work);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
register_word(vm, "VM-ERROR?", mama_word_vm_error_query);
|
||||
@@ -2458,7 +2421,6 @@ void register_mama_forth_words(VM *vm)
|
||||
register_word(vm, "VM-PHYSICS-STATUS", mama_word_vm_physics_status);
|
||||
register_word(vm, "VM-STEP", mama_word_vm_step);
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "SWITCH-MARK-WORK", mama_word_switch_mark_work);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
register_word(vm, "VM-ERROR?", mama_word_vm_error_query);
|
||||
@@ -2719,7 +2681,6 @@ void register_child_vm_words(VM *vm)
|
||||
register_word(vm, "STOP", mama_word_stop);
|
||||
register_word(vm, "EXEC", mama_word_exec);
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "SWITCH-MARK-WORK", mama_word_switch_mark_work);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
register_word(vm, "VM-ERROR?", mama_word_vm_error_query);
|
||||
|
||||
+12
-43
@@ -47,7 +47,6 @@
|
||||
#include "starkernel/vm/bootstrap/sk_vm_bootstrap.h"
|
||||
#include "starkernel/vm/kernel_hermes.h" /* FABRIC-3.6.md task 3.8 -- sk_hermes_send_one() */
|
||||
#include "starkernel/vm/switch.h" /* FABRIC-3.8.md §3.13.5 -- sk_vm_idle_point() */
|
||||
#include "starkernel/capsule_vm_switch_signal.h" /* §3.13.5 -- pump skips participants */
|
||||
#include "starkernel/vm/stadium.h" /* task 3.8 -- stadium_conserved() evidence print */
|
||||
#include "block_subsystem.h"
|
||||
#include "word_source/include/keyboard_words.h"
|
||||
@@ -954,48 +953,18 @@ static void sk_repl_idle(VM *active_vm)
|
||||
}
|
||||
|
||||
g_idle_pump_active = 1;
|
||||
{
|
||||
/* FABRIC-3.6.md Phase 4 (Stage E), 2026-09-22: the SK_MSG_PUMP_
|
||||
* BATCH cap this loop used to enforce existed to bound the cost
|
||||
* of the old MSG-TICK VM-EXEC dispatch -- a genuinely expensive
|
||||
* per-VM vm_interpret() call, confirmed live as a real O(N)
|
||||
* bottleneck at just 9 VMs on riscv64 (see this section's own
|
||||
* history above). sk_hermes_drain_checkpoint() (task 3.4) is not
|
||||
* that: its own fast path is a single global-counter read
|
||||
* (sk_hermes_pending_total == 0 -> return immediately,
|
||||
* kernel_hermes.c's own doc comment), so walking every live VM
|
||||
* every beat costs one cheap integer read per VM in the common
|
||||
* case (nothing in flight), not an O(N) wall -- the cap this
|
||||
* loop's own comment history worried about does not apply to
|
||||
* this call. Removed: every live VM (except mama, handled
|
||||
* separately below) is now visited every idle beat, matching
|
||||
* what task 3.9's own testing already exercised, without the
|
||||
* ceil(N/SK_MSG_PUMP_BATCH)-beat delivery latency the cap was
|
||||
* accidentally imposing on kernel-Hermes drain specifically. */
|
||||
uint32_t count = capsule_vm_registry_count();
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
VMRegistryEntry ent;
|
||||
/* FABRIC-3.8.md §3.4 / §3.13.5 (Stage C-b, G3): switch
|
||||
* participants are skipped -- their mail is delivered on their
|
||||
* own stacks, by a switch (sk_vm_idle_point() and the trampoline),
|
||||
* never drained here on Hera's. Only VMs not yet participants
|
||||
* (Stage E makes every born VM one) are still pumped here. */
|
||||
if (capsule_vm_registry_get_by_index(i, &ent) == 0 &&
|
||||
ent.state == VM_STATE_LIVE &&
|
||||
ent.vm_ptr != (void *)mama &&
|
||||
!sk_vm_switch_signal_is_participant(ent.vm_id)) {
|
||||
(void)sk_hermes_drain_checkpoint((VM *)ent.vm_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Hera's own kernel-Hermes queue needs draining too, same as every
|
||||
* other VM's -- she is excluded from the loop above not because she
|
||||
* has nothing to drain, but because she IS the pump: a self-
|
||||
* targeting call here runs directly, no VM-EXEC/reentrancy concern
|
||||
* (sk_hermes_drain_checkpoint() is a plain C call, not a dispatch
|
||||
* into anyone else's input buffer). */
|
||||
/* FABRIC-3.8.md Stage I (2026-09-24): the loop that used to drain every
|
||||
* other live VM's queue here, on Hera's stack (G3), is removed. Since
|
||||
* Stage E every born VM is a switch participant -- births are capped at
|
||||
* stadium_max_vm_count() live VMs (capsule_birth.c), the same capacity
|
||||
* as the switch-signal table, so registration cannot fail -- and a
|
||||
* participant's mail is delivered on its own stack by a switch, never
|
||||
* here. Shown dead three ways before removal: by the condition it
|
||||
* required (a live non-participant), by that construction, and at run
|
||||
* time (a probe printed nothing through a boot, the Stage G interleave,
|
||||
* a full 8-worker DoE trial and the WIREBIND relay). What remains is
|
||||
* Hera's own queue: she is the one VM that is never switched to for her
|
||||
* mail, since she is the one running here. */
|
||||
(void)sk_hermes_drain_checkpoint(mama);
|
||||
g_idle_pump_active = 0;
|
||||
|
||||
|
||||
@@ -49,8 +49,9 @@ extern uint64_t sk_vm_switch_prime(uint64_t stack_top, void *entry);
|
||||
* native stack belongs to. Read exactly once, synchronously, at the very
|
||||
* top of sk_vm_switch_entry() before any other first-entry could occur.
|
||||
* Safe to keep as a plain global (unlike the old g_switch_back_to this
|
||||
* file used to also carry -- see native_switch_back_to's own doc comment
|
||||
* in vm.h for why that one had to move to per-VM state): a VM's identity
|
||||
* file used to also carry, which moved to per-VM native_switch_back_to and
|
||||
* was then removed at FABRIC-3.8.md Stage I once the trampoline stopped
|
||||
* yielding to "whoever switched in"): a VM's identity
|
||||
* never changes across the lifetime of its own trampoline instance, only
|
||||
* who most recently switched into it does. */
|
||||
static VM *g_switch_entry_vm;
|
||||
@@ -236,11 +237,6 @@ int sk_vm_context_switch(VM *from, VM *to) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Recorded unconditionally (first-ever entry or a resume) so whoever
|
||||
* is parked at `to`'s native stack -- most often this placeholder
|
||||
* trampoline -- always knows who most recently switched into it. */
|
||||
to->native_switch_back_to = from;
|
||||
|
||||
if (to->native_stack_saved_sp == 0) {
|
||||
/* First-ever entry: synthesize the initial frame. */
|
||||
g_switch_entry_vm = to;
|
||||
|
||||
@@ -65,11 +65,6 @@
|
||||
#include "starkernel/vm/kernel_hermes.h" /* FABRIC-3.6.md task 3.4 -- sk_hermes_drain_checkpoint() */
|
||||
#include "starkernel/capsule_birth.h" /* capsule_vm_registry_get() */
|
||||
|
||||
/* FABRIC-3.md §XXVIII Stage 3 correction (2026-09-13): forward-declared
|
||||
* here because execute_colon_word() (uses it) appears earlier in this file
|
||||
* than g_vm_interpret_depth's definition (kept next to g_log_attrib_vm,
|
||||
* near vm_interpret() -- see that doc comment for the full rationale). */
|
||||
int sk_vm_at_outermost_interpret(void);
|
||||
int sk_vm_owns_outermost_frame(VM *vm); /* FABRIC-3.8.md §3.1 -- defined near vm_interpret() */
|
||||
#endif
|
||||
#include "word_source/include/vocabulary_words.h"
|
||||
@@ -940,8 +935,9 @@ void execute_colon_word(VM* vm)
|
||||
* so a switch never happens mid-unwind).
|
||||
*
|
||||
* Stage 3 correction (2026-09-13): also gated on
|
||||
* sk_vm_at_outermost_interpret() -- see g_vm_interpret_depth's own
|
||||
* doc comment above vm_interpret(). If this word is executing
|
||||
* sk_vm_at_outermost_interpret() (a global depth count, removed at
|
||||
* FABRIC-3.8.md Stage I -- superseded by the ownership gate
|
||||
* below). If this word is executing
|
||||
* nested inside a VM-EXEC/VM-CALL dispatch (from another VM's own
|
||||
* vm_interpret() call, still on the mainline stack), `vm` here does
|
||||
* not own the physical stack it's currently running on, so a real
|
||||
@@ -1174,19 +1170,11 @@ VM *vm_log_attributed_vm(void) {
|
||||
return (VM *)e.vm_ptr;
|
||||
}
|
||||
|
||||
/* FABRIC-3.md §XXVIII Stage 3 correction (2026-09-13): nesting depth of
|
||||
* vm_interpret() calls, tracked the same save/restore-adjacent way as
|
||||
* g_log_attrib_vm just above. A nested call (VM-EXEC/VM-CALL dispatching
|
||||
* into a different VM's own dictionary mid-interpret) runs on physical
|
||||
* stack memory it does not own -- the Stage 3 switch checkpoint in
|
||||
* execute_colon_word() below must never fire a real context switch there,
|
||||
* only at the outermost vm_interpret() call, or it parks a borrowed stack
|
||||
* region under the wrong VM's saved-context pointer (silent corruption,
|
||||
* not just the trampoline livelock this was first found chasing -- see
|
||||
* FABRIC-3.md for the full writeup). */
|
||||
static int g_vm_interpret_depth;
|
||||
|
||||
int sk_vm_at_outermost_interpret(void) { return g_vm_interpret_depth <= 1; }
|
||||
/* FABRIC-3.8.md Stage I (2026-09-24): the global vm_interpret() nesting
|
||||
* depth (g_vm_interpret_depth / sk_vm_at_outermost_interpret(), FABRIC-3.md
|
||||
* §XXVIII Stage 3) that used to live here is removed. It only approximated
|
||||
* the per-VM ownership rule below, and stopped meaning anything once VMs
|
||||
* interleave on their own stacks; since Stage A nothing read it. */
|
||||
|
||||
/* FABRIC-3.8.md §3.1 (Stage A, 2026-09-23): the real ownership invariant
|
||||
* the global depth test above was approximating. A checkpoint may drain or
|
||||
@@ -1252,7 +1240,6 @@ void vm_interpret_kind(VM* vm, const char* input, uint32_t kind)
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
g_vm_interpret_depth++;
|
||||
|
||||
/* Load into input buffer (cap + NUL) */
|
||||
size_t n = 0, cap = INPUT_BUFFER_SIZE ? INPUT_BUFFER_SIZE - 1 : 0;
|
||||
@@ -1303,7 +1290,6 @@ void vm_interpret_kind(VM* vm, const char* input, uint32_t kind)
|
||||
#endif
|
||||
}
|
||||
|
||||
g_vm_interpret_depth--;
|
||||
vm_frame_pop(frame_stack, frame_id); /* by ID -- a mismatch is logged as corruption */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user