Skip to main content

strat9_kernel/process/
test.rs

1//! Test module for the scheduler
2//!
3//! Contains simple test tasks to verify that the scheduler is working correctly.
4//! Includes both a cooperative task and a busy-loop task to demonstrate
5//! preemptive scheduling.
6
7use crate::process::{add_task, Task, TaskPriority};
8
9/// Creates and adds test tasks to the scheduler
10pub fn create_test_tasks() {
11    // Cooperative test task (yields voluntarily)
12    let test_task = Task::new_kernel_task(test_task_main, "test-coop", TaskPriority::Normal)
13        .expect("Failed to create cooperative test task");
14    add_task(test_task);
15
16    // Busy-loop test task (never yields — relies on preemption)
17    let busy_task = Task::new_kernel_task(busy_task_main, "test-busy", TaskPriority::Normal)
18        .expect("Failed to create busy test task");
19    add_task(busy_task);
20}
21
22/// Main function for the cooperative test task
23extern "C" fn test_task_main() -> ! {
24    crate::serial_println!("[test-coop] Cooperative test task started!");
25    let mut counter = 0u64;
26
27    // Run for a limited number of iterations to allow keyboard input
28    let max_iterations = 100_000; // Adjust this value as needed
29
30    loop {
31        if counter % 1000 == 0 {
32            crate::serial_println!("[test-coop] iteration {}", counter);
33        }
34
35        // Check if we've reached our iteration limit
36        if counter >= max_iterations {
37            crate::serial_println!("[test-coop] Iteration limit reached, exiting task");
38            break;
39        }
40
41        counter += 1;
42
43        // Cooperatively yield to other tasks
44        crate::process::yield_task();
45    }
46
47    // Exit the current task to allow keyboard input
48    crate::process::scheduler::exit_current_task(0);
49}
50
51/// Main function for the busy-loop test task (never yields).
52///
53/// If preemption is working, this task will be forcibly interrupted by the
54/// timer and other tasks will still get CPU time. If preemption is broken,
55/// this task will starve everything else.
56///
57/// This task now runs for approximately 3-5 seconds then exits to allow keyboard input.
58extern "C" fn busy_task_main() -> ! {
59    crate::serial_println!("[test-busy] Busy-loop test task started (never yields)!");
60    let mut counter = 0u64;
61
62    // Assuming ~100 iterations per millisecond with preemption at 100Hz
63    // So 300,000 to 500,000 iterations = 3-5 seconds
64    let max_iterations = 400_000; // Adjust this value as needed
65
66    loop {
67        if counter % 5_000_000 == 0 {
68            crate::serial_println!("[test-busy] iteration {} (preemption works!)", counter);
69        }
70
71        // Check if we've reached our time limit
72        if counter >= max_iterations {
73            crate::serial_println!("[test-busy] Time limit reached, exiting task");
74            break;
75        }
76
77        counter += 1;
78        // No yield! Timer preemption is the only way other tasks run.
79    }
80
81    // Exit the current task to allow keyboard input
82    crate::process::scheduler::exit_current_task(0);
83}