⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/sched/
runtime.rs

1//! Scheduler runtime loop and idle task management
2//!
3//! Contains the main scheduler execution loop (`run`), the idle task entry
4//! point, timer tick handling, and scheduler start/query functions.
5
6use super::scheduler;
7
8/// Start the scheduler
9///
10/// This transfers control to the scheduler, which will run the current task
11/// (bootstrap or idle) and never return.
12pub fn start() -> ! {
13    kprintln!("[SCHED] Starting scheduler execution");
14
15    #[cfg(target_arch = "aarch64")]
16    {
17        // Enter idle loop
18        loop {
19            // SAFETY: WFI (Wait For Interrupt) is a hint instruction that
20            // puts the CPU into a low-power state until an interrupt arrives.
21            // It does not modify any memory or registers beyond the PC. The
22            // nomem/nostack/preserves_flags options correctly reflect this.
23            unsafe {
24                core::arch::asm!("wfi", options(nomem, nostack, preserves_flags));
25            }
26        }
27    }
28
29    #[cfg(target_arch = "riscv64")]
30    {
31        // Enter idle loop
32        loop {
33            // SAFETY: WFI (Wait For Interrupt) is a hint instruction on RISC-V
34            // that suspends execution until an interrupt occurs. It does not
35            // modify memory or registers. The options correctly reflect this.
36            unsafe {
37                core::arch::asm!("wfi", options(nomem, nostack, preserves_flags));
38            }
39        }
40    }
41
42    // x86_64: Enter HLT idle loop (matches AArch64 WFI and RISC-V WFI)
43    #[cfg(target_arch = "x86_64")]
44    {
45        println!("[SCHED] Entering idle loop");
46        loop {
47            crate::arch::idle();
48        }
49    }
50}
51
52/// Check if there are ready tasks
53pub fn has_ready_tasks() -> bool {
54    #[cfg(not(target_arch = "riscv64"))]
55    {
56        super::READY_QUEUE.lock().has_ready_tasks()
57    }
58    #[cfg(target_arch = "riscv64")]
59    {
60        super::queue::get_ready_queue().has_ready_tasks()
61    }
62}
63
64/// Run scheduler main loop (called by idle task)
65pub fn run() -> ! {
66    kprintln!("[SCHED] Entering scheduler main loop");
67
68    let mut balance_counter = 0u64;
69
70    loop {
71        // Check for ready tasks
72        #[cfg(not(target_arch = "riscv64"))]
73        {
74            if super::READY_QUEUE.lock().has_ready_tasks() {
75                super::SCHEDULER.lock().schedule();
76            }
77        }
78        #[cfg(target_arch = "riscv64")]
79        {
80            if super::queue::get_ready_queue().has_ready_tasks() {
81                super::SCHEDULER.lock().schedule();
82            }
83        }
84
85        // Periodically perform load balancing and cleanup
86        balance_counter = balance_counter.wrapping_add(1);
87        if balance_counter.is_multiple_of(1000) {
88            #[cfg(feature = "alloc")]
89            {
90                super::load_balance::balance_load();
91
92                // Also clean up dead tasks
93                if balance_counter.is_multiple_of(10000) {
94                    super::load_balance::cleanup_dead_tasks();
95                }
96            }
97        }
98
99        // Enter low power state
100        crate::arch::idle();
101    }
102}
103
104/// Idle task entry point
105pub extern "C" fn idle_task_entry() -> ! {
106    run()
107}
108
109/// Handle timer tick
110pub fn timer_tick() {
111    scheduler::current_scheduler().lock().tick();
112}
113
114/// Set scheduling algorithm
115pub fn set_algorithm(algorithm: super::SchedAlgorithm) {
116    super::SCHEDULER.lock().algorithm = algorithm;
117}