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}