diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 5df327294..c8f1e1bb7 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -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!() } diff --git a/kernel/src/sched/priority_scheduler.rs b/kernel/src/sched/priority_scheduler.rs index b2aaecdad..15a602dce 100644 --- a/kernel/src/sched/priority_scheduler.rs +++ b/kernel/src/sched/priority_scheduler.rs @@ -53,7 +53,9 @@ impl PreemptScheduler { 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 Scheduler for PreemptScheduler { 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 { current: Option>, real_time_entities: VecDeque>, normal_entities: VecDeque>, + lowest_entities: VecDeque>, } impl PreemptRunQueue { @@ -124,6 +129,7 @@ impl PreemptRunQueue { current: None, real_time_entities: VecDeque::new(), normal_entities: VecDeque::new(), + lowest_entities: VecDeque::new(), } } } @@ -149,12 +155,16 @@ impl LocalRunQueue for PreemptRunQueue fn pick_next_current(&mut self) -> Option<&Arc> { 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 PreemptSchedEntity { 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 + } } diff --git a/ostd/src/task/scheduler/info.rs b/ostd/src/task/scheduler/info.rs index baaf32588..37b353d5c 100644 --- a/ostd/src/task/scheduler/info.rs +++ b/ostd/src/task/scheduler/info.rs @@ -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`.