Don't preempt without good reason

This commit is contained in:
Ruihan Li
2024-10-31 10:00:19 +08:00
committed by Tate, Hongliang Tian
parent 19b13d88e2
commit 5233827160
6 changed files with 32 additions and 16 deletions

View File

@ -93,8 +93,6 @@ pub fn main() {
ThreadOptions::new(init_thread) ThreadOptions::new(init_thread)
.priority(Priority::new(PriorityRange::new(PriorityRange::MAX))), .priority(Priority::new(PriorityRange::new(PriorityRange::MAX))),
); );
// Spawning functions in the bootstrap context will not return.
unreachable!()
} }
pub fn init() { pub fn init() {
@ -110,7 +108,7 @@ pub fn init() {
process::init(); process::init();
} }
fn ap_init() -> ! { fn ap_init() {
fn ap_idle_thread() { fn ap_idle_thread() {
let preempt_guard = ostd::task::disable_preempt(); let preempt_guard = ostd::task::disable_preempt();
let cpu_id = preempt_guard.current_cpu(); let cpu_id = preempt_guard.current_cpu();
@ -129,8 +127,6 @@ fn ap_init() -> ! {
.cpu_affinity(cpu_id.into()) .cpu_affinity(cpu_id.into())
.priority(Priority::new(PriorityRange::new(PriorityRange::MAX))), .priority(Priority::new(PriorityRange::new(PriorityRange::MAX))),
); );
// Spawning functions in the bootstrap context will not return.
unreachable!()
} }
fn init_thread() { fn init_thread() {

View File

@ -104,6 +104,9 @@ impl<T: Sync + Send + PreemptSchedInfo + FromTask<U>, U: Sync + Send + CommonSch
if still_in_rq && let Err(_) = entity.task.cpu().set_if_is_none(target_cpu) { if still_in_rq && let Err(_) = entity.task.cpu().set_if_is_none(target_cpu) {
return None; return None;
} }
let new_priority = entity.thread.priority();
if entity.thread.is_real_time() { if entity.thread.is_real_time() {
rq.real_time_entities.push_back(entity); rq.real_time_entities.push_back(entity);
} else if entity.thread.is_lowest() { } else if entity.thread.is_lowest() {
@ -112,7 +115,17 @@ impl<T: Sync + Send + PreemptSchedInfo + FromTask<U>, U: Sync + Send + CommonSch
rq.normal_entities.push_back(entity); rq.normal_entities.push_back(entity);
} }
// 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) Some(target_cpu)
} else {
None
}
} }
fn local_rq_with(&self, f: &mut dyn FnMut(&dyn LocalRunQueue<U>)) { fn local_rq_with(&self, f: &mut dyn FnMut(&dyn LocalRunQueue<U>)) {

View File

@ -49,9 +49,7 @@ fn main() {
}; };
}; };
let _ = TaskOptions::new(test_task).data(()).spawn(); TaskOptions::new(test_task).data(()).spawn().unwrap();
unreachable!("The spawn method will NOT return in the boot context")
} }
#[ostd::ktest::panic_handler] #[ostd::ktest::panic_handler]

View File

@ -30,8 +30,10 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
#[cfg(not(ktest))] #[cfg(not(ktest))]
#[no_mangle] #[no_mangle]
extern "Rust" fn __ostd_main() -> ! { extern "Rust" fn __ostd_main() -> ! {
#main_fn_name(); let _: () = #main_fn_name();
ostd::prelude::abort();
ostd::task::Task::yield_now();
unreachable!("`yield_now` in the boot context should not return");
} }
#[allow(unused)] #[allow(unused)]
@ -52,8 +54,10 @@ pub fn test_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
quote!( quote!(
#[no_mangle] #[no_mangle]
extern "Rust" fn __ostd_main() -> ! { extern "Rust" fn __ostd_main() -> ! {
#main_fn_name(); let _: () = #main_fn_name();
ostd::prelude::abort();
ostd::task::Task::yield_now();
unreachable!("`yield_now` in the boot context should not return");
} }
#main_fn #main_fn

View File

@ -15,6 +15,7 @@ use crate::{
page::{self, meta::KernelMeta, ContPages}, page::{self, meta::KernelMeta, ContPages},
PAGE_SIZE, PAGE_SIZE,
}, },
task::Task,
}; };
pub(crate) static AP_BOOT_INFO: Once<ApBootInfo> = Once::new(); pub(crate) static AP_BOOT_INFO: Once<ApBootInfo> = Once::new();
@ -37,7 +38,7 @@ struct PerApInfo {
boot_stack_pages: ContPages<KernelMeta>, boot_stack_pages: ContPages<KernelMeta>,
} }
static AP_LATE_ENTRY: Once<fn() -> !> = Once::new(); static AP_LATE_ENTRY: Once<fn()> = Once::new();
/// Boot all application processors. /// Boot all application processors.
/// ///
@ -104,7 +105,7 @@ pub fn boot_all_aps() {
/// ///
/// Once the entry function is registered, all the application processors /// Once the entry function is registered, all the application processors
/// will jump to the entry function immediately. /// 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); 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(); let ap_late_entry = AP_LATE_ENTRY.wait();
ap_late_entry(); ap_late_entry();
Task::yield_now();
unreachable!("`yield_now` in the boot context should not return");
} }
fn wait_for_all_aps_started() { fn wait_for_all_aps_started() {

View File

@ -58,7 +58,8 @@ impl<T: CommonSchedInfo + Send + Sync> Scheduler<T> for FifoScheduler<T> {
} }
rq.queue.push_back(runnable); 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<T>)) { fn local_rq_with(&self, f: &mut dyn FnMut(&dyn LocalRunQueue<T>)) {