diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index abf1d26ec..861e40c22 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -93,8 +93,6 @@ pub fn main() { ThreadOptions::new(init_thread) .priority(Priority::new(PriorityRange::new(PriorityRange::MAX))), ); - // Spawning functions in the bootstrap context will not return. - unreachable!() } pub fn init() { @@ -110,7 +108,7 @@ pub fn init() { process::init(); } -fn ap_init() -> ! { +fn ap_init() { fn ap_idle_thread() { let preempt_guard = ostd::task::disable_preempt(); let cpu_id = preempt_guard.current_cpu(); @@ -129,8 +127,6 @@ fn ap_init() -> ! { .cpu_affinity(cpu_id.into()) .priority(Priority::new(PriorityRange::new(PriorityRange::MAX))), ); - // Spawning functions in the bootstrap context will not return. - unreachable!() } fn init_thread() { diff --git a/kernel/src/sched/priority_scheduler.rs b/kernel/src/sched/priority_scheduler.rs index b3e61317f..2d6be77f8 100644 --- a/kernel/src/sched/priority_scheduler.rs +++ b/kernel/src/sched/priority_scheduler.rs @@ -104,6 +104,9 @@ impl, U: Sync + Send + CommonSch if still_in_rq && let Err(_) = entity.task.cpu().set_if_is_none(target_cpu) { return None; } + + let new_priority = entity.thread.priority(); + if entity.thread.is_real_time() { rq.real_time_entities.push_back(entity); } else if entity.thread.is_lowest() { @@ -112,7 +115,17 @@ impl, U: Sync + Send + CommonSch rq.normal_entities.push_back(entity); } - Some(target_cpu) + // Preempt the current task, but only if the newly queued task has a strictly higher + // priority (i.e., a lower value returned by the `priority` method) than the current task. + if rq + .current + .as_ref() + .is_some_and(|current| new_priority < current.thread.priority()) + { + Some(target_cpu) + } else { + None + } } fn local_rq_with(&self, f: &mut dyn FnMut(&dyn LocalRunQueue)) { diff --git a/osdk/test-kernel/src/lib.rs b/osdk/test-kernel/src/lib.rs index a02f0790c..ff2ecbfd8 100644 --- a/osdk/test-kernel/src/lib.rs +++ b/osdk/test-kernel/src/lib.rs @@ -49,9 +49,7 @@ fn main() { }; }; - let _ = TaskOptions::new(test_task).data(()).spawn(); - - unreachable!("The spawn method will NOT return in the boot context") + TaskOptions::new(test_task).data(()).spawn().unwrap(); } #[ostd::ktest::panic_handler] diff --git a/ostd/libs/ostd-macros/src/lib.rs b/ostd/libs/ostd-macros/src/lib.rs index 91b031c01..ad733aa8d 100644 --- a/ostd/libs/ostd-macros/src/lib.rs +++ b/ostd/libs/ostd-macros/src/lib.rs @@ -30,8 +30,10 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream { #[cfg(not(ktest))] #[no_mangle] extern "Rust" fn __ostd_main() -> ! { - #main_fn_name(); - ostd::prelude::abort(); + let _: () = #main_fn_name(); + + ostd::task::Task::yield_now(); + unreachable!("`yield_now` in the boot context should not return"); } #[allow(unused)] @@ -52,8 +54,10 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream { quote!( #[no_mangle] extern "Rust" fn __ostd_main() -> ! { - #main_fn_name(); - ostd::prelude::abort(); + let _: () = #main_fn_name(); + + ostd::task::Task::yield_now(); + unreachable!("`yield_now` in the boot context should not return"); } #main_fn diff --git a/ostd/src/boot/smp.rs b/ostd/src/boot/smp.rs index 41808fa6d..8c071806d 100644 --- a/ostd/src/boot/smp.rs +++ b/ostd/src/boot/smp.rs @@ -15,6 +15,7 @@ use crate::{ page::{self, meta::KernelMeta, ContPages}, PAGE_SIZE, }, + task::Task, }; pub(crate) static AP_BOOT_INFO: Once = Once::new(); @@ -37,7 +38,7 @@ struct PerApInfo { boot_stack_pages: ContPages, } -static AP_LATE_ENTRY: Once !> = Once::new(); +static AP_LATE_ENTRY: Once = Once::new(); /// Boot all application processors. /// @@ -104,7 +105,7 @@ pub fn boot_all_aps() { /// /// Once the entry function is registered, all the application processors /// will jump to the entry function immediately. -pub fn register_ap_entry(entry: fn() -> !) { +pub fn register_ap_entry(entry: fn()) { AP_LATE_ENTRY.call_once(|| entry); } @@ -150,6 +151,9 @@ fn ap_early_entry(local_apic_id: u32) -> ! { let ap_late_entry = AP_LATE_ENTRY.wait(); ap_late_entry(); + + Task::yield_now(); + unreachable!("`yield_now` in the boot context should not return"); } fn wait_for_all_aps_started() { diff --git a/ostd/src/task/scheduler/fifo_scheduler.rs b/ostd/src/task/scheduler/fifo_scheduler.rs index 77aae536a..6fd3aed1b 100644 --- a/ostd/src/task/scheduler/fifo_scheduler.rs +++ b/ostd/src/task/scheduler/fifo_scheduler.rs @@ -58,7 +58,8 @@ impl Scheduler for FifoScheduler { } rq.queue.push_back(runnable); - Some(target_cpu) + // All tasks are important. Do not preempt the current task without good reason. + None } fn local_rq_with(&self, f: &mut dyn FnMut(&dyn LocalRunQueue)) {