Change idle task to lowest priority

This commit is contained in:
Yuke Peng 2024-09-10 10:32:41 +08:00 committed by Tate, Hongliang Tian
parent 1186fb7ca9
commit 63364813a8
3 changed files with 41 additions and 10 deletions

View File

@ -37,6 +37,7 @@ use ostd::{
arch::qemu::{exit_qemu, QemuExitCode},
boot,
cpu::PinCurrentCpu,
task::Priority,
};
use process::Process;
@ -90,7 +91,7 @@ pub fn main() {
ostd::boot::smp::register_ap_entry(ap_init);
// Spawn the first kernel thread on BSP.
Thread::spawn_kernel_thread(ThreadOptions::new(init_thread));
Thread::spawn_kernel_thread(ThreadOptions::new(init_thread).priority(Priority::lowest()));
// Spawning functions in the bootstrap context will not return.
unreachable!()
}
@ -122,7 +123,11 @@ fn ap_init() -> ! {
let cpu_id = preempt_guard.current_cpu();
drop(preempt_guard);
Thread::spawn_kernel_thread(ThreadOptions::new(ap_idle_thread).cpu_affinity(cpu_id.into()));
Thread::spawn_kernel_thread(
ThreadOptions::new(ap_idle_thread)
.cpu_affinity(cpu_id.into())
.priority(Priority::lowest()),
);
// Spawning functions in the bootstrap context will not return.
unreachable!()
}

View File

@ -53,7 +53,9 @@ impl<T: PreemptSchedInfo> PreemptScheduler<T> {
let rq = self.rq[candidate].lock();
// A wild guess measuring the load of a runqueue. We assume that
// real-time tasks are 4-times as important as normal tasks.
let load = rq.real_time_entities.len() * 4 + rq.normal_entities.len();
let load = rq.real_time_entities.len() * 8
+ rq.normal_entities.len() * 2
+ rq.lowest_entities.len();
if load < minimum_load {
selected = candidate as u32;
minimum_load = load;
@ -85,6 +87,8 @@ impl<T: Sync + Send + PreemptSchedInfo> Scheduler<T> for PreemptScheduler<T> {
let entity = PreemptSchedEntity::new(runnable);
if entity.is_real_time() {
rq.real_time_entities.push_back(entity);
} else if entity.is_lowest() {
rq.lowest_entities.push_back(entity);
} else {
rq.normal_entities.push_back(entity);
}
@ -116,6 +120,7 @@ struct PreemptRunQueue<T: PreemptSchedInfo> {
current: Option<PreemptSchedEntity<T>>,
real_time_entities: VecDeque<PreemptSchedEntity<T>>,
normal_entities: VecDeque<PreemptSchedEntity<T>>,
lowest_entities: VecDeque<PreemptSchedEntity<T>>,
}
impl<T: PreemptSchedInfo> PreemptRunQueue<T> {
@ -124,6 +129,7 @@ impl<T: PreemptSchedInfo> PreemptRunQueue<T> {
current: None,
real_time_entities: VecDeque::new(),
normal_entities: VecDeque::new(),
lowest_entities: VecDeque::new(),
}
}
}
@ -149,12 +155,16 @@ impl<T: Sync + Send + PreemptSchedInfo> LocalRunQueue<T> for PreemptRunQueue<T>
fn pick_next_current(&mut self) -> Option<&Arc<T>> {
let next_entity = if !self.real_time_entities.is_empty() {
self.real_time_entities.pop_front()
} else {
} else if !self.normal_entities.is_empty() {
self.normal_entities.pop_front()
} else {
self.lowest_entities.pop_front()
}?;
if let Some(prev_entity) = self.current.replace(next_entity) {
if prev_entity.is_real_time() {
self.real_time_entities.push_back(prev_entity);
} else if prev_entity.is_lowest() {
self.lowest_entities.push_back(prev_entity);
} else {
self.normal_entities.push_back(prev_entity);
}
@ -190,6 +200,10 @@ impl<T: PreemptSchedInfo> PreemptSchedEntity<T> {
self.runnable.is_real_time()
}
fn is_lowest(&self) -> bool {
self.runnable.is_lowest()
}
fn tick(&mut self) -> bool {
self.time_slice.elapse()
}
@ -233,6 +247,7 @@ impl PreemptSchedInfo for Task {
type PRIORITY = Priority;
const REAL_TIME_TASK_PRIORITY: Self::PRIORITY = Priority::new(100);
const LOWEST_TASK_PRIORITY: Self::PRIORITY = Priority::lowest();
fn priority(&self) -> Self::PRIORITY {
self.schedule_info().priority
@ -251,6 +266,7 @@ trait PreemptSchedInfo {
type PRIORITY: Ord + PartialOrd + Eq + PartialEq;
const REAL_TIME_TASK_PRIORITY: Self::PRIORITY;
const LOWEST_TASK_PRIORITY: Self::PRIORITY;
fn priority(&self) -> Self::PRIORITY;
@ -261,4 +277,8 @@ trait PreemptSchedInfo {
fn is_real_time(&self) -> bool {
self.priority() < Self::REAL_TIME_TASK_PRIORITY
}
fn is_lowest(&self) -> bool {
self.priority() == Self::LOWEST_TASK_PRIORITY
}
}

View File

@ -35,39 +35,45 @@ pub const REAL_TIME_TASK_PRIORITY: u16 = 100;
pub struct Priority(u16);
impl Priority {
const LOWEST: u16 = 139;
const LOW: u16 = 110;
const NORMAL: u16 = 100;
const HIGH: u16 = 10;
const HIGHEST: u16 = 0;
/// Creates a new `Priority` with the specified value.
///
/// # Panics
///
/// Panics if the `val` is greater than 139.
pub const fn new(val: u16) -> Self {
assert!(val <= 139);
assert!(val <= Self::LOWEST);
Self(val)
}
/// Returns a `Priority` representing the lowest priority (139).
pub const fn lowest() -> Self {
Self::new(139)
Self::new(Self::LOWEST)
}
/// Returns a `Priority` representing a low priority.
pub const fn low() -> Self {
Self::new(110)
Self::new(Self::LOW)
}
/// Returns a `Priority` representing a normal priority.
pub const fn normal() -> Self {
Self::new(100)
Self::new(Self::NORMAL)
}
/// Returns a `Priority` representing a high priority.
pub const fn high() -> Self {
Self::new(10)
Self::new(Self::HIGH)
}
/// Returns a `Priority` representing the highest priority (0).
pub const fn highest() -> Self {
Self::new(0)
Self::new(Self::HIGHEST)
}
/// Sets the value of the `Priority`.