Files
SUB-OS/kernel/main.c
T
Claude a14a7c79b0 feat(sched): Weave tiered scheduler with real kernel-thread context switching
Replace the state-relabel-only round-robin with the SUB-OS "Weave"
scheduler backed by a genuine callee-saved context switch. Threads now
actually run on their own kernel stacks instead of merely having their
state field rewritten.

What was implemented:
- sub_ctx_switch(): per-arch assembly (arch/x86_64/cpu/switch.asm,
  arch/aarch64/cpu/switch.S, arch/armv8i/cpu/switch.S) that saves/restores
  the callee-saved register set (+ flags on x86_64) on each thread's own
  stack, plus a first-run trampoline (sub_thread_trampoline) that launches
  a freshly forged thread frame with entry/arg in callee-saved registers.
- task_forge_frame(): builds the initial saved-context frame per arch so
  the very first switch into a new thread lands on the trampoline; task_t
  gains a pointer-sized ctx_sp so the same struct works on 64- and 32-bit.
- Weave policy (kernel/sched.c): WEAVE_NLANES priority lanes, always
  dispatch the lowest non-empty lane round-robin; a task that yields
  voluntarily is woven UP a lane (interactive), one preempted after
  burning its quantum is woven DOWN (CPU-bound). Cooperative switching
  (sched_yield / task_exit) is always live; timer-driven preemption is
  gated behind sched_set_preempt() and left disarmed for now.
- task_exit() now switches to the next runnable thread via
  sched_exit_current() instead of spinning/halting.
- Boot-time weave_selftest() (x86_64) and sched_dump() diagnostics.

How it was verified:
- Builds clean for all three targets: x86_64 (CROSS_COMPILE=x86_64-linux-gnu-,
  RUSTC="rustc --target x86_64-unknown-none"), aarch64, armv8i. No new
  warnings; the new x86_64 asm carries a .note.GNU-stack section.
- Booted x86_64 under QEMU (TCG): the self-test runs three cooperative
  kernel threads to completion on separate stacks with the expected
  1->2->3 round-robin interleave, reports "20 real context switches,
  3/3 workers exited", returns cleanly to the boot thread, and boot
  proceeds normally to ring-3 init and the shell. No fault/panic.

Left unverified:
- The aarch64/armv8i sub_ctx_switch frames build and link but are not yet
  boot-tested on their QEMU targets (tracked in docs/AUTODEV_ROADMAP.md).
- Timer preemption path is implemented but disarmed; exited kernel threads
  currently leak their stack (reaper is next in the backlog).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Jk6K69yGS7zYgvoWd6nJxQ
2026-08-25 08:16:37 +00:00

365 lines
11 KiB
C

#include <kernel/kernel.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/task.h>
#include <kernel/signal.h>
#include <kernel/syscall.h>
#include <kernel/timer.h>
#include <kernel/workqueue.h>
#include <kernel/module.h>
#include <kernel/trace.h>
#include <kernel/namespace.h>
#include <kernel/syslog.h>
#include <kernel/cron.h>
#include <kernel/metrics.h>
#include <kernel/bpf.h>
#include <kernel/kobject.h>
#include <kernel/wait.h>
#include <kernel/futex.h>
#include <kernel/rcu.h>
#include <kernel/ktest.h>
#include <mm/page_cache.h>
#include <mm/vma.h>
#include <drivers/canvas.h>
#include <drivers/pty.h>
#include <arch/arch.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <mm/slab.h>
#include <drivers/tty.h>
#include <drivers/serial.h>
#include <drivers/keyboard.h>
#include <drivers/mouse.h>
#include <drivers/ata.h>
#include <drivers/ahci.h>
#include <drivers/nvme.h>
#include <drivers/bochs.h>
#include <drivers/virtio_blk.h>
#include <drivers/virtio_net.h>
#include <drivers/virtio_rng.h>
#include <drivers/hwmon.h>
#include <drivers/pci.h>
#include <drivers/e1000.h>
#include <drivers/rtl8139.h>
#include <drivers/speaker.h>
#include <drivers/fb.h>
#include <drivers/rtc.h>
#include <drivers/acpi.h>
#include <drivers/usb.h>
#include <drivers/xhci.h>
#include <drivers/ramdisk.h>
#include <block/block.h>
#include <ipc/ipc.h>
#include <sound/sound.h>
#include <sound/hda.h>
#include <sound/melody.h>
#include <fs/vfs.h>
#include <fs/fat32.h>
#include <fs/ext2.h>
#include <fs/sysfs.h>
#include <net/net.h>
#include <net/socket.h>
#include <net/udp.h>
#include <net/tcp.h>
#include <net/dhcp.h>
#include <net/dns.h>
#include <net/dns_cache.h>
#include <ipc/shm_posix.h>
#include <sound/beep.h>
#include <kernel/tsc.h>
#include <drivers/e1000e.h>
#include <drivers/virtio_gpu.h>
#include <drivers/cpufreq.h>
#include <drivers/virtio_input.h>
#include <kernel/rust.h>
#include <kernel/sub_lang.h>
#include <kernel/cpp_kernel.h>
#include <net/filter.h>
#include <net/http.h>
#include <net/ssh.h>
#include <crypto/crypto.h>
#include <certs/certs.h>
#include <security/security.h>
#include <security/auth.h>
#include <io_uring/io_uring.h>
#include <usr/initramfs.h>
#include <virt/virt.h>
#include <init/init.h>
#include <init/service.h>
#include <init/version.h>
#include <init/bootlogo.h>
#include <drivers/fbcon.h>
#include <userland/lazybox.h>
#include <userland/sh.h>
#include <userland/shell.h>
#include <kernel/exec.h>
static void subos_modular_core_boot(void) {
#if defined(__x86_64__)
pci_init();
#endif
// Storage & Block Layer
printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... ");
block_init();
page_cache_init();
ramdisk_init();
#if defined(__x86_64__)
ata_init();
ahci_init();
nvme_init();
#endif
virtio_blk_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Bus & Devices
printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... ");
#if defined(__x86_64__)
virt_init();
fb_init();
bochs_vbe_init();
virtio_gpu_init();
usb_init();
xhci_init();
hwmon_init();
cpufreq_init();
#endif
canvas_init();
pty_init();
virtio_rng_init();
virtio_input_init();
tsc_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// The framebuffer exists from here on. This kernel boots to a text console,
// so the graphical splash is opt-in via `splash` on the command line --
// raising it by default would hide the very console we are about to use.
// The ASCII logo printed at the top of boot covers the default case.
if (init_has_param("splash") && !init_has_param("nosplash")) {
boot_logo_splash_begin();
} else {
// The adapter is in graphics mode from here on, so the VGA text buffer
// is no longer scanned out. Move the console to the framebuffer or the
// rest of the boot log is visible only on the serial line.
fbcon_enable(true);
}
// Network Subsystem, NetFilter, HTTPD & SSH Server
printk(KERN_INFO "[6/14] Initializing Network Stack, NetFilter, HTTPD & SSHD... ");
boot_logo_splash_progress(40, "Bringing up the network stack");
filter_init();
httpd_init();
sshd_init();
#if defined(__x86_64__)
rtl8139_init();
virtio_net_init();
e1000e_init();
if (e1000_init() || e1000e_is_online()) {
net_init();
socket_subsystem_init();
udp_init();
tcp_init();
dhcp_init();
dns_init();
dns_cache_init();
printk(ANSI_BRIGHT_GREEN "Online\n" ANSI_RESET);
} else {
printk(ANSI_YELLOW "No NIC detected\n" ANSI_RESET);
}
#else
virtio_net_init();
dns_cache_init();
printk(ANSI_BRIGHT_GREEN "Online\n" ANSI_RESET);
#endif
// Sound & Voice Synthesizer
#if defined(__x86_64__)
printk(KERN_INFO "[7/14] Initializing Sound Architecture, Melody Player & Formant TTS... ");
sound_init();
hda_init();
melody_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
#endif
// Crypto, Certificates, LSM Security, Authentication, Namespaces, Rust, SUB-Lang & C++ Subsystems
printk(KERN_INFO "[8/14] Initializing Rust, C++ Core, SUB-Lang Engine, Keyring & Auth... ");
boot_logo_splash_progress(55, "Starting Rust, C++ and SUB-Lang engines");
rust_kernel_init();
cpp_kernel_init();
sub_kernel_init();
prng_seed(0, 0);
certs_init();
security_init();
auth_init();
namespace_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Concurrency Primitives: Wait Queues, Futexes & Tiny RCU
printk(KERN_INFO "[9/14] Initializing Wait Queues, Futex Hash & Tiny RCU... ");
boot_logo_splash_progress(65, "Initializing concurrency primitives");
wait_subsystem_init();
futex_init();
rcu_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Inter-Process Communication
printk(KERN_INFO "[9/14] Initializing IPC Engine (Pipes, MsgQueues, POSIX SHM, Semaphores)... ");
ipc_init();
posix_shm_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Asynchronous I/O Engine
printk(KERN_INFO "[10/14] Initializing io_uring Async Ring Engine... ");
io_uring_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Virtual File System & Multi-Filesystem Support
printk(KERN_INFO "[11/14] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... ");
boot_logo_splash_progress(78, "Mounting the virtual file system");
vfs_init();
sysfs_init();
kobject_subsystem_init();
fat32_init();
ext2_init();
initramfs_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd
printk(KERN_INFO "[12/14] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... ");
boot_logo_splash_progress(88, "Starting kernel services");
signal_init();
workqueue_init();
syscall_init();
module_init_subsystem();
trace_init();
bpf_init();
syslog_init();
metrics_init();
cron_init();
service_manager_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Preemptive Multi-Tasking & Userland
printk(KERN_INFO "[13/14] Initializing Preemptive Task Scheduler & LazyBox... ");
boot_logo_splash_progress(95, "Starting the scheduler and userland");
sched_init();
lazybox_init();
ktest_init();
ktest_register_builtin_suites();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
#if defined(__x86_64__)
/* Prove real kernel-thread context switching before hardware interrupts
* are enabled: the Weave scheduler drives a batch of cooperative threads
* to completion on their own stacks and returns cleanly to this boot
* thread. Interrupts are still masked here, so the run is deterministic. */
weave_selftest();
#endif
// Hardware Interrupts
printk(KERN_INFO "[14/14] Enabling Hardware Interrupts... ");
arch_enable_interrupts();
printk(ANSI_BRIGHT_GREEN "ACTIVE\n" ANSI_RESET);
// Return the screen to the console before handing over to the shell.
boot_logo_splash_end();
fbcon_enable(true);
// Hand control to userland: /sbin/init is a separate static ELF that runs
// in ring 3 with its own page tables and talks back only through INT 0x80.
exec_run_builtin_init();
// Launch Shell
shell_run();
while (1) {
arch_halt();
}
}
#if defined(__x86_64__)
void kernel_main(void* memory_map, uint64_t memory_map_count) {
tty_init();
serial_init();
printk_init();
boot_logo_print_text();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/sda console=tty1 init=/bin/lazybox video=1280x720 quiet");
rtc_init();
printk(KERN_INFO "[1/14] Initializing 64-Bit GDT, IDT, PIC & PIT Timer... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing PS/2 Keyboard, Mouse & ACPI... ");
keyboard_init();
mouse_init();
acpi_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[3/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(memory_map, memory_map_count);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#elif defined(__aarch64__)
void kernel_main_aarch64(void) {
arch_early_init();
printk_init();
boot_logo_print_text();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/vda console=ttyAMA0 init=/bin/lazybox quiet");
printk(KERN_INFO "[1/14] Initializing AArch64 CPU, GICv2, Generic Timer & MMU... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(NULL, 0);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#elif defined(__arm__) || defined(__armv8i__)
void kernel_main_armv8i(void) {
arch_early_init();
printk_init();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 32-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/vda console=ttyAMA0 init=/bin/lazybox quiet");
printk(KERN_INFO "[1/14] Initializing ARMv8i CPU, GICv2, Generic Timer & MMU... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(NULL, 0);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#endif