From c778f6e0e716e9eaca296077398bf92c9d3dfc6a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 12 Nov 2026 18:04:31 +0000 Subject: [PATCH] fix(v4): the kernel's fatal stops halt, interrupts off, instead of spinning (#177) sk_v4_run's three stops -- "not started", "did not let go of POST's blocks", "stopped on a fault" -- ended in for (;;) { }: a core spinning at 100%, the thing #151 removed from the prompt. Each now calls sk_v4_stop() (kernel/src/v4/sk_v4_stop.c): interrupts off, then arch_halt() for ever. Each still says why first. sk_v4_stop.c added to the loader's and the kernel's v4 sources. kernel/tests/test_sk_v4_stop.c, with arch_halt and arch_disable_interrupts faked (the halt jumps back out after three calls; an alarm fails a spin): against the stop as it was -- "spun for 2 s without halting"; now -- 2 checks, 0 failures: halts in a loop, interrupts off before the first halt. Built for amd64, aarch64 and riscv64. #177's "seen on the three architectures": no boot reaches these stops, so it is shown on the host only. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm --- kernel/Makefile | 4 +- kernel/include/starkernel/v4/sk_v4_stop.h | 12 ++++++ kernel/src/v4/sk_v4.c | 7 +-- kernel/src/v4/sk_v4_stop.c | 14 ++++++ kernel/tests/Makefile | 3 +- kernel/tests/test_sk_v4_stop.c | 43 +++++++++++++++++++ .../kernel-tests/test_sk_v4_stop.log | 3 ++ 7 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 kernel/include/starkernel/v4/sk_v4_stop.h create mode 100644 kernel/src/v4/sk_v4_stop.c create mode 100644 kernel/tests/test_sk_v4_stop.c create mode 100644 logs/20261112-180431/kernel-tests/test_sk_v4_stop.log diff --git a/kernel/Makefile b/kernel/Makefile index 2782b1b2..ec6025e3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -730,8 +730,8 @@ V4_ENGINE_SRCS := $(addprefix v4/src/,node.c exec.c stack.c iword.c heat.c guard V4_ROM_C := $(BUILD_DIR)/v4_rom_64.c V4_MAP_C := $(BUILD_DIR)/v4_map_64.c -LOADER_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c $(KERNEL_SRC)/v4/sk_v4_grow.c $(KERNEL_SRC)/v4/sk_v4_mint.c -KERNEL_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c $(KERNEL_SRC)/v4/sk_v4_grow.c $(KERNEL_SRC)/v4/sk_v4_mint.c +LOADER_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c $(KERNEL_SRC)/v4/sk_v4_grow.c $(KERNEL_SRC)/v4/sk_v4_mint.c $(KERNEL_SRC)/v4/sk_v4_stop.c +KERNEL_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c $(KERNEL_SRC)/v4/sk_v4_grow.c $(KERNEL_SRC)/v4/sk_v4_mint.c $(KERNEL_SRC)/v4/sk_v4_stop.c # v4/system/boot.c is the boot the hosted v4 system runs too: the ROM # assembles the system, then the capsules from this kernel's own capsule # directory, then the prompt. diff --git a/kernel/include/starkernel/v4/sk_v4_stop.h b/kernel/include/starkernel/v4/sk_v4_stop.h new file mode 100644 index 00000000..5e92ca16 --- /dev/null +++ b/kernel/include/starkernel/v4/sk_v4_stop.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LicenseRef-Starship-1.0 + * Copyright (c) 2023-2026 Robert A. James + */ +/* sk_v4_stop.h -- the v4 kernel's fatal stop (#177): what sk_v4_run does when the system cannot + * go on ("not started", "did not let go of POST's blocks", "stopped on a fault"). Never returns. + */ +#ifndef STARKERNEL_V4_SK_V4_STOP_H +#define STARKERNEL_V4_SK_V4_STOP_H + +void sk_v4_stop(void) __attribute__((noreturn)); + +#endif diff --git a/kernel/src/v4/sk_v4.c b/kernel/src/v4/sk_v4.c index 2b09b601..ba294f52 100644 --- a/kernel/src/v4/sk_v4.c +++ b/kernel/src/v4/sk_v4.c @@ -26,6 +26,7 @@ #include "starkernel/v4/sk_v4_mint.h" #include "starkernel/v4/sk_v4.h" #include "starkernel/v4/sk_v4_identity.h" +#include "starkernel/v4/sk_v4_stop.h" #include "starkernel/kbd_input.h" #include "starkernel/console.h" #include "starkernel/arch.h" @@ -159,7 +160,7 @@ void sk_v4_run(void (*chain)(void), const BootDisk *boot_disk) blk_subsys_init(sk_v4_post_blk_ram, sizeof(sk_v4_post_blk_ram)); if (!v4_boot_run(&boot)) { console_println("StarForth v4: not started"); - for (;;) { } + sk_v4_stop(); /* #177: halts, not a 100% spin */ } if (chain) { /* the blocks are other blocks now: what the node has in its two @@ -167,7 +168,7 @@ void sk_v4_run(void (*chain)(void), const BootDisk *boot_disk) chain(); if (v4_boot_line(&boot, "EMPTY-BUFFERS", 13) != V4_TEXT_COMPLETED) { console_println("StarForth v4: the node did not let go of POST's blocks"); - for (;;) { } + sk_v4_stop(); /* #177: halts, not a 100% spin */ } } sk_v4_identity_boot(boot_disk); @@ -230,7 +231,7 @@ void sk_v4_run(void (*chain)(void), const BootDisk *boot_disk) else if (how == V4_BOOT_LINE_REFUSED) console_puts("Message refused\n ERROR\n"); /* the node's wire is full: error 19's words */ else if (how == V4_BOOT_LINE_STOPPED) { console_println("StarForth v4: the node stopped on a fault"); - for (;;) { } + sk_v4_stop(); /* #177: halts, not a 100% spin */ } } } diff --git a/kernel/src/v4/sk_v4_stop.c b/kernel/src/v4/sk_v4_stop.c new file mode 100644 index 00000000..a5e33f38 --- /dev/null +++ b/kernel/src/v4/sk_v4_stop.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LicenseRef-Starship-1.0 + * Copyright (c) 2023-2026 Robert A. James + */ +/* sk_v4_stop.c -- see sk_v4_stop.h. */ +#include "starkernel/v4/sk_v4_stop.h" +#include "starkernel/arch.h" + +/* Interrupts off, then halt for ever: the core sleeps instead of spinning at 100% (#177), and no + * timer or device wakes it to do anything. sk_v4_run's three stops each said why first. */ +void sk_v4_stop(void) +{ + arch_disable_interrupts(); + for (;;) arch_halt(); +} diff --git a/kernel/tests/Makefile b/kernel/tests/Makefile index a15ae74e..69d3a995 100644 --- a/kernel/tests/Makefile +++ b/kernel/tests/Makefile @@ -19,7 +19,8 @@ CC ?= cc CFLAGS := -std=c99 -Wall -Wextra -Werror -O2 -g -I$(HERE) -I$(ROOT)/kernel/include \ -I$(ROOT)/kernel/include/starkernel -I$(ROOT)/v3/include -TESTS := test_gpt test_usb_config +TESTS := test_gpt test_usb_config test_sk_v4_stop +SRC_test_sk_v4_stop := $(ROOT)/kernel/src/v4/sk_v4_stop.c SRC_test_gpt := $(ROOT)/kernel/src/gpt.c SRC_test_usb_config := $(ROOT)/kernel/src/usb/usb_config.c diff --git a/kernel/tests/test_sk_v4_stop.c b/kernel/tests/test_sk_v4_stop.c new file mode 100644 index 00000000..467f56ba --- /dev/null +++ b/kernel/tests/test_sk_v4_stop.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LicenseRef-Starship-1.0 + * Copyright (c) 2023-2026 Robert A. James + */ +/* test_sk_v4_stop.c -- kernel/src/v4/sk_v4_stop.c on the host (#177): the v4 kernel's fatal stops + * halt -- interrupts off, then arch_halt() in a loop -- instead of spinning a core at 100%. + * arch_halt() and arch_disable_interrupts() are faked: the fake halt counts, and after a few calls + * jumps back out of the loop. A stop that spins never calls it: an alarm ends the test as failed. + */ +#define _POSIX_C_SOURCE 200809L +#include "harness.h" +#include "starkernel/v4/sk_v4_stop.h" +#include +#include +#include + +static jmp_buf out; +static int halts, irq_off, irq_off_before_first_halt = -1; + +void arch_disable_interrupts(void) { irq_off = 1; } +void arch_enable_interrupts(void) { irq_off = 0; } +void arch_halt(void) +{ + if (irq_off_before_first_halt < 0) irq_off_before_first_halt = irq_off; + if (++halts >= 3) longjmp(out, 1); /* it is halting, again and again: enough */ +} +static void spun(int sig) +{ + (void)sig; + static const char msg[] = "FAIL sk_v4_stop spun for 2 s without halting (#177)\n 1 checks, 1 failures\n"; + (void)!write(1, msg, sizeof msg - 1); /* not printf: _exit would not flush it */ + _exit(1); +} + +int main(void) +{ + signal(SIGALRM, spun); + alarm(2); + if (setjmp(out) == 0) sk_v4_stop(); + alarm(0); + CHECK(halts == 3, "#177: the stop halts in a loop (arch_halt called %d times before the test stopped it)", halts); + CHECK(irq_off_before_first_halt == 1, "#177: interrupts off before the first halt, so nothing wakes it to spin again"); + return DONE(); +} diff --git a/logs/20261112-180431/kernel-tests/test_sk_v4_stop.log b/logs/20261112-180431/kernel-tests/test_sk_v4_stop.log new file mode 100644 index 00000000..ddf00bcb --- /dev/null +++ b/logs/20261112-180431/kernel-tests/test_sk_v4_stop.log @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d651855e23868989758681f308c02bbf7ed68729ea5d48ff9a2003ac9623e160 +size 269