/* StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. This file is part of the StarForth project. Licensed under the StarForth License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://github.com/star.4th@proton.me/StarForth/LICENSE.txt This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the License for the specific language governing permissions and limitations under the License. */ /** * capsule_vm_switch_signal.h - New, purpose-built "who runs next" signal * for preemptive context switching (FABRIC-3.md §XXVIII, Stage 3, * 2026-09-13). * * Deliberately NOT a repurposing of capsule_vm_physics.c's execution-heat * engine -- that measures word-level dispatch fairness over millions of * executions on a different timescale, and its own header explicitly * documents it as never touched from interrupt context (unlocked, by * design). This is a different physical quantity: instant-by-instant * run-readiness, consulted from real ISR context (heartbeat_tick()) every * timer tick. * * Concurrency discipline mirrors heartbeat.c's own §21.1-sanctioned * pattern for heartbeat_next_period_ns(): single-writer-ISR (tick()) / * single-reader-mainline (take_pending(), called from the cooperative * checkpoint in execute_colon_word()), no lock, because nothing on this * single hart is concurrent with the ISR while it runs. * * NOT truly interrupt-driven register/stack swapping (that was * considered and rejected for this stage -- see FABRIC-3.md §XXVIII * Stage 3 for why): the ISR only ever sets a flag. The actual switch * (Stage 2's already-proven sk_vm_context_switch()) happens later, at a * safe cooperative checkpoint on the mainline, once per word dispatch. * * Slot table is sized with headroom, not hardcoded to exactly today's 3 * participants (Hera/Hermes/Artemis) -- extending participation later * (Stage 4+) is another sk_vm_switch_signal_register() call, not a * redesign. */ #ifndef STARKERNEL_CAPSULE_VM_SWITCH_SIGNAL_H #define STARKERNEL_CAPSULE_VM_SWITCH_SIGNAL_H #ifdef __STARKERNEL__ #include #include "starkernel/vm_uuid.h" /* Register a VM as a switch-signal participant. Returns its slot index, * or -1 if the slot table is full. Call once per participating VM, * after that VM is fully born (never mid-birth -- this stage has no * critical-section protection against being switched away mid-setup). */ int sk_vm_switch_signal_register(VMUuid vm_id); /* Called from heartbeat_tick() (ISR context) every timer tick. Cheap: * iterates only the registered slots (bounded, small). */ void sk_vm_switch_signal_tick(void); /* Called from the cooperative checkpoint (execute_colon_word(), mainline, * once per word dispatch). Returns the VMUuid of a VM that should now be * switched to, or vm_uuid_none() if nothing is pending. Clears the * pending flag as a side effect -- call at most once per checkpoint. */ 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); /* 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 * decision itself; these just make it observable. */ uint64_t sk_vm_switch_signal_switch_count(void); /* cumulative, since boot */ uint32_t sk_vm_switch_signal_ticks_since_switch(void); int sk_vm_switch_signal_current_slot(void); /* -1 = none/unregistered */ int sk_vm_switch_signal_slot_count(void); uint32_t sk_vm_switch_signal_readiness(int slot); /* 0 if slot out of range */ uint32_t sk_vm_switch_signal_readiness_of(VMUuid vm_id); /* 0 if not registered */ #endif /* __STARKERNEL__ */ #endif /* STARKERNEL_CAPSULE_VM_SWITCH_SIGNAL_H */