mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Remove priority field from OSTD Task struct
This commit is contained in:
parent
0a36760f7a
commit
8927031426
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -164,12 +164,9 @@ dependencies = [
|
||||
"aster-time",
|
||||
"aster-util",
|
||||
"aster-virtio",
|
||||
"atomic",
|
||||
"atomic-integer-wrapper",
|
||||
"bitflags 1.3.2",
|
||||
"bitvec",
|
||||
"bytemuck",
|
||||
"bytemuck_derive",
|
||||
"cfg-if",
|
||||
"component",
|
||||
"controlled",
|
||||
@ -266,15 +263,6 @@ dependencies = [
|
||||
"typeflags-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-integer-wrapper"
|
||||
version = "0.1.0"
|
||||
@ -1345,6 +1333,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"defmt",
|
||||
"heapless",
|
||||
"log",
|
||||
"managed",
|
||||
]
|
||||
|
||||
|
@ -55,9 +55,6 @@ rand = { version = "0.8.5", default-features = false, features = [
|
||||
static_assertions = "1.1.0"
|
||||
inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e" }
|
||||
getset = "0.1.2"
|
||||
atomic = "0.6"
|
||||
bytemuck = "1.17.0"
|
||||
bytemuck_derive = "1.7.1"
|
||||
takeable = "0.2.2"
|
||||
cfg-if = "1.0"
|
||||
|
||||
|
@ -37,12 +37,13 @@ use ostd::{
|
||||
arch::qemu::{exit_qemu, QemuExitCode},
|
||||
boot,
|
||||
cpu::PinCurrentCpu,
|
||||
task::Priority,
|
||||
};
|
||||
use process::Process;
|
||||
use sched::priority::PriorityRange;
|
||||
|
||||
use crate::{
|
||||
prelude::*,
|
||||
sched::priority::Priority,
|
||||
thread::{
|
||||
kernel_thread::{KernelThreadExt, ThreadOptions},
|
||||
Thread,
|
||||
@ -91,7 +92,10 @@ 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).priority(Priority::lowest()));
|
||||
Thread::spawn_kernel_thread(
|
||||
ThreadOptions::new(init_thread)
|
||||
.priority(Priority::new(PriorityRange::new(PriorityRange::MAX))),
|
||||
);
|
||||
// Spawning functions in the bootstrap context will not return.
|
||||
unreachable!()
|
||||
}
|
||||
@ -126,7 +130,7 @@ fn ap_init() -> ! {
|
||||
Thread::spawn_kernel_thread(
|
||||
ThreadOptions::new(ap_idle_thread)
|
||||
.cpu_affinity(cpu_id.into())
|
||||
.priority(Priority::lowest()),
|
||||
.priority(Priority::new(PriorityRange::new(PriorityRange::MAX))),
|
||||
);
|
||||
// Spawning functions in the bootstrap context will not return.
|
||||
unreachable!()
|
||||
|
@ -4,10 +4,11 @@ use alloc::sync::Arc;
|
||||
use core::time::Duration;
|
||||
|
||||
use log::trace;
|
||||
use ostd::{arch::timer::Jiffies, task::Priority};
|
||||
use ostd::arch::timer::Jiffies;
|
||||
|
||||
use super::{ext::IfaceEx, Iface, IFACES};
|
||||
use crate::{
|
||||
sched::priority::{Priority, PriorityRange},
|
||||
thread::{
|
||||
kernel_thread::{KernelThreadExt, ThreadOptions},
|
||||
Thread,
|
||||
@ -68,6 +69,7 @@ fn spawn_background_poll_thread(iface: Arc<Iface>) {
|
||||
}
|
||||
};
|
||||
|
||||
let options = ThreadOptions::new(task_fn).priority(Priority::high());
|
||||
// FIXME: remove the use of real-time priority.
|
||||
let options = ThreadOptions::new(task_fn).priority(Priority::new(PriorityRange::new(0)));
|
||||
Thread::spawn_kernel_thread(options);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use crate::{
|
||||
signal::{sig_mask::AtomicSigMask, sig_queues::SigQueues},
|
||||
Credentials, Process,
|
||||
},
|
||||
sched::priority::Priority,
|
||||
thread::{status::ThreadStatus, task, Thread, Tid},
|
||||
time::{clocks::ProfClock, TimerManager},
|
||||
};
|
||||
@ -111,7 +112,13 @@ impl PosixThreadBuilder {
|
||||
};
|
||||
|
||||
let status = ThreadStatus::Init;
|
||||
let thread = Arc::new(Thread::new(weak_task.clone(), posix_thread, status));
|
||||
let priority = Priority::default();
|
||||
let thread = Arc::new(Thread::new(
|
||||
weak_task.clone(),
|
||||
posix_thread,
|
||||
status,
|
||||
priority,
|
||||
));
|
||||
|
||||
thread_table::add_thread(tid, thread.clone());
|
||||
task::create_new_user_task(user_space, thread)
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
signal::sig_disposition::SigDispositions,
|
||||
Credentials,
|
||||
},
|
||||
sched::nice::Nice,
|
||||
sched::priority::Nice,
|
||||
};
|
||||
|
||||
pub struct ProcessBuilder<'a> {
|
||||
|
@ -20,7 +20,7 @@ use crate::{
|
||||
device::tty::open_ntty_as_controlling_terminal,
|
||||
fs::{file_table::FileTable, fs_resolver::FsResolver, utils::FileCreationMask},
|
||||
prelude::*,
|
||||
sched::nice::Nice,
|
||||
sched::priority::{AtomicNice, Nice},
|
||||
thread::Thread,
|
||||
time::clocks::ProfClock,
|
||||
vm::vmar::Vmar,
|
||||
@ -34,7 +34,6 @@ mod terminal;
|
||||
mod timer_manager;
|
||||
|
||||
use aster_rights::Full;
|
||||
use atomic::Atomic;
|
||||
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
pub use builder::ProcessBuilder;
|
||||
pub use job_control::JobControl;
|
||||
@ -93,7 +92,7 @@ pub struct Process {
|
||||
/// Scheduling priority nice value
|
||||
/// According to POSIX.1, the nice value is a per-process attribute,
|
||||
/// the threads in a process should share a nice value.
|
||||
nice: Atomic<Nice>,
|
||||
nice: AtomicNice,
|
||||
|
||||
// Signal
|
||||
/// Sig dispositions
|
||||
@ -223,7 +222,7 @@ impl Process {
|
||||
parent_death_signal: AtomicSigNum::new_empty(),
|
||||
exit_signal: AtomicSigNum::new_empty(),
|
||||
resource_limits: Mutex::new(resource_limits),
|
||||
nice: Atomic::new(nice),
|
||||
nice: AtomicNice::new(nice),
|
||||
timer_manager: PosixTimerManager::new(&prof_clock, process_ref),
|
||||
prof_clock,
|
||||
})
|
||||
@ -329,7 +328,7 @@ impl Process {
|
||||
&self.resource_limits
|
||||
}
|
||||
|
||||
pub fn nice(&self) -> &Atomic<Nice> {
|
||||
pub fn nice(&self) -> &AtomicNice {
|
||||
&self.nice
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
pub mod nice;
|
||||
pub mod priority;
|
||||
mod priority_scheduler;
|
||||
|
||||
// There may be multiple scheduling policies in the system,
|
||||
|
@ -1,103 +0,0 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use bytemuck_derive::NoUninit;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
/// The process scheduling nice value.
|
||||
///
|
||||
/// The nice value is an attribute that can be used to influence the
|
||||
/// CPU scheduler to favor or disfavor a process in scheduling decisions.
|
||||
///
|
||||
/// It is a value in the range -20 to 19, with -20 being the highest priority
|
||||
/// and 19 being the lowest priority. The smaller values give a process a higher
|
||||
/// scheduling priority.
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, NoUninit)]
|
||||
pub struct Nice {
|
||||
value: i8,
|
||||
}
|
||||
|
||||
impl Nice {
|
||||
/// The minimum nice, whose value is -20.
|
||||
pub const MIN: Self = Self { value: -20 };
|
||||
|
||||
/// The maximum nice, whose value is 19.
|
||||
pub const MAX: Self = Self { value: 19 };
|
||||
|
||||
/// Creates a new `Nice` from the raw value.
|
||||
///
|
||||
/// Values given beyond the permissible range are automatically adjusted
|
||||
/// to the nearest boundary value.
|
||||
pub fn new(raw: i8) -> Self {
|
||||
Self {
|
||||
value: raw.clamp(Self::MIN.to_raw(), Self::MAX.to_raw()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to the raw value.
|
||||
pub fn to_raw(self) -> i8 {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for Nice {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
// The default nice value is 0
|
||||
value: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Priority> for Nice {
|
||||
fn from(priority: Priority) -> Self {
|
||||
Self {
|
||||
value: 20 - priority.to_raw() as i8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The process scheduling priority value.
|
||||
///
|
||||
/// It is a value in the range 1 (corresponding to a nice value of 19)
|
||||
/// to 40 (corresponding to a nice value of -20), with 1 being the lowest priority
|
||||
/// and 40 being the highest priority. The greater values give a process a higher
|
||||
/// scheduling priority.
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, NoUninit)]
|
||||
pub struct Priority {
|
||||
value: u8,
|
||||
}
|
||||
|
||||
impl Priority {
|
||||
/// The minimum priority, whose value is 1.
|
||||
pub const MIN: Self = Self { value: 1 };
|
||||
|
||||
/// The maximum priority, whose value is 40.
|
||||
pub const MAX: Self = Self { value: 40 };
|
||||
|
||||
/// Creates a new `Priority` from the raw value.
|
||||
///
|
||||
/// Values given beyond the permissible range are automatically adjusted
|
||||
/// to the nearest boundary value.
|
||||
pub fn new(raw: u8) -> Self {
|
||||
Self {
|
||||
value: raw.clamp(Self::MIN.to_raw(), Self::MAX.to_raw()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to the raw value.
|
||||
pub fn to_raw(self) -> u8 {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Nice> for Priority {
|
||||
fn from(nice: Nice) -> Self {
|
||||
Self {
|
||||
value: (20 - nice.to_raw()) as u8,
|
||||
}
|
||||
}
|
||||
}
|
159
kernel/src/sched/priority.rs
Normal file
159
kernel/src/sched/priority.rs
Normal file
@ -0,0 +1,159 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::{AtomicI8, AtomicU8};
|
||||
|
||||
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
|
||||
/// The process scheduling nice value.
|
||||
///
|
||||
/// It is an integer in the range of [-20, 19]. Process with a smaller nice
|
||||
/// value is more favorable in scheduling.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Nice(NiceRange);
|
||||
|
||||
pub type NiceRange = RangedI8<-20, 19>;
|
||||
|
||||
define_atomic_version_of_integer_like_type!(Nice, try_from = true, {
|
||||
#[derive(Debug)]
|
||||
pub struct AtomicNice(AtomicI8);
|
||||
});
|
||||
|
||||
impl Nice {
|
||||
pub const fn new(range: NiceRange) -> Self {
|
||||
Self(range)
|
||||
}
|
||||
|
||||
pub fn range(&self) -> &NiceRange {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn range_mut(&mut self) -> &mut NiceRange {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Nice {
|
||||
fn default() -> Self {
|
||||
Self::new(NiceRange::new(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Nice> for i8 {
|
||||
fn from(value: Nice) -> Self {
|
||||
value.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<i8> for Nice {
|
||||
type Error = <NiceRange as TryFrom<i8>>::Error;
|
||||
|
||||
fn try_from(value: i8) -> Result<Self, Self::Error> {
|
||||
let range = value.try_into()?;
|
||||
Ok(Self::new(range))
|
||||
}
|
||||
}
|
||||
|
||||
/// The thread scheduling priority value.
|
||||
///
|
||||
/// It is an integer in the range of [0, 139]. Here we follow the Linux
|
||||
/// priority mappings: the relation between [`Priority`] and [`Nice`] is
|
||||
/// as such - prio = nice + 120 while the priority of [0, 100] are
|
||||
/// reserved for real-time tasks.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct Priority(PriorityRange);
|
||||
|
||||
pub type PriorityRange = RangedU8<0, 139>;
|
||||
|
||||
define_atomic_version_of_integer_like_type!(Priority, try_from = true, {
|
||||
#[derive(Debug)]
|
||||
pub struct AtomicPriority(AtomicU8);
|
||||
});
|
||||
|
||||
impl Priority {
|
||||
pub const fn new(range: PriorityRange) -> Self {
|
||||
Self(range)
|
||||
}
|
||||
|
||||
pub fn range(&self) -> &PriorityRange {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn range_mut(&mut self) -> &mut PriorityRange {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Nice> for Priority {
|
||||
fn from(value: Nice) -> Self {
|
||||
Self::new(PriorityRange::new(value.range().get() as u8 + 120))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Priority {
|
||||
fn default() -> Self {
|
||||
Nice::default().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Priority> for u8 {
|
||||
fn from(value: Priority) -> Self {
|
||||
value.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Priority {
|
||||
type Error = <PriorityRange as TryFrom<u8>>::Error;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
let range = value.try_into()?;
|
||||
Ok(Self::new(range))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_ranged_integer {
|
||||
($visibility: vis, $name: ident, $type: ty) => {
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
$visibility struct $name<const MIN: $type, const MAX: $type>($type);
|
||||
|
||||
impl<const MIN: $type, const MAX: $type> $name<MIN, MAX> {
|
||||
$visibility const MIN: $type = MIN as $type;
|
||||
$visibility const MAX: $type = MAX as $type;
|
||||
|
||||
$visibility const fn new(val: $type) -> Self {
|
||||
assert!(val >= MIN && val <= MAX);
|
||||
Self(val)
|
||||
}
|
||||
|
||||
$visibility fn set(&mut self, val: $type) {
|
||||
assert!(val >= MIN && val <= MAX);
|
||||
self.0 = val;
|
||||
}
|
||||
|
||||
$visibility fn get(self) -> $type {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const MIN: $type, const MAX: $type> From<$name<MIN, MAX>> for $type {
|
||||
fn from(value: $name<MIN, MAX>) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const MIN: $type, const MAX: $type> TryFrom<$type> for $name<MIN, MAX> {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(value: $type) -> Result<Self, Self::Error> {
|
||||
if value < Self::MIN || value > Self::MAX {
|
||||
Err("Initialized with out-of-range value.")
|
||||
} else {
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_ranged_integer!(pub, RangedI8, i8);
|
||||
|
||||
define_ranged_integer!(pub, RangedU8, u8);
|
@ -4,12 +4,13 @@ use ostd::{
|
||||
cpu::{num_cpus, CpuSet, PinCurrentCpu},
|
||||
task::{
|
||||
scheduler::{inject_scheduler, EnqueueFlags, LocalRunQueue, Scheduler, UpdateFlags},
|
||||
AtomicCpuId, Priority, Task,
|
||||
AtomicCpuId, Task,
|
||||
},
|
||||
trap::disable_local,
|
||||
};
|
||||
|
||||
use crate::prelude::*;
|
||||
use super::priority::{Priority, PriorityRange};
|
||||
use crate::{prelude::*, thread::Thread};
|
||||
|
||||
pub fn init() {
|
||||
let preempt_scheduler = Box::new(PreemptScheduler::default());
|
||||
@ -244,13 +245,14 @@ impl Default for TimeSlice {
|
||||
}
|
||||
|
||||
impl PreemptSchedInfo for Task {
|
||||
type PRIORITY = Priority;
|
||||
const REAL_TIME_TASK_PRIORITY: Priority = Priority::new(PriorityRange::new(100));
|
||||
const LOWEST_TASK_PRIORITY: Priority = Priority::new(PriorityRange::new(PriorityRange::MAX));
|
||||
|
||||
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
|
||||
fn priority(&self) -> Priority {
|
||||
self.data()
|
||||
.downcast_ref::<Arc<Thread>>()
|
||||
.unwrap()
|
||||
.priority()
|
||||
}
|
||||
|
||||
fn cpu(&self) -> &AtomicCpuId {
|
||||
@ -263,12 +265,10 @@ impl PreemptSchedInfo for Task {
|
||||
}
|
||||
|
||||
trait PreemptSchedInfo {
|
||||
type PRIORITY: Ord + PartialOrd + Eq + PartialEq;
|
||||
const REAL_TIME_TASK_PRIORITY: Priority;
|
||||
const LOWEST_TASK_PRIORITY: Priority;
|
||||
|
||||
const REAL_TIME_TASK_PRIORITY: Self::PRIORITY;
|
||||
const LOWEST_TASK_PRIORITY: Self::PRIORITY;
|
||||
|
||||
fn priority(&self) -> Self::PRIORITY;
|
||||
fn priority(&self) -> Priority;
|
||||
|
||||
fn cpu(&self) -> &AtomicCpuId;
|
||||
|
||||
|
@ -6,14 +6,14 @@ use super::SyscallReturn;
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::{posix_thread::PosixThreadExt, process_table, Pgid, Pid, Process, Uid},
|
||||
sched::nice::Nice,
|
||||
sched::priority::{Nice, NiceRange},
|
||||
};
|
||||
|
||||
pub fn sys_set_priority(which: i32, who: u32, prio: i32, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let prio_target = PriorityTarget::new(which, who, ctx)?;
|
||||
let new_nice = {
|
||||
let norm_prio = prio.clamp(i8::MIN as i32, i8::MAX as i32) as i8;
|
||||
Nice::new(norm_prio)
|
||||
let nice_raw = prio.clamp(NiceRange::MIN as i32, NiceRange::MAX as i32) as i8;
|
||||
Nice::new(NiceRange::new(nice_raw))
|
||||
};
|
||||
|
||||
debug!(
|
||||
@ -35,9 +35,9 @@ pub fn sys_get_priority(which: i32, who: u32, ctx: &Context) -> Result<SyscallRe
|
||||
|
||||
let processes = get_processes(prio_target)?;
|
||||
let highest_prio = {
|
||||
let mut nice = Nice::MAX;
|
||||
let mut nice = NiceRange::MAX;
|
||||
for process in processes.iter() {
|
||||
let proc_nice = process.nice().load(Ordering::Relaxed);
|
||||
let proc_nice = process.nice().load(Ordering::Relaxed).range().get();
|
||||
// Returns the highest priority enjoyed by the processes
|
||||
if proc_nice < nice {
|
||||
nice = proc_nice;
|
||||
@ -46,7 +46,7 @@ pub fn sys_get_priority(which: i32, who: u32, ctx: &Context) -> Result<SyscallRe
|
||||
|
||||
// The system call returns nice values translated to the range 40 to 1,
|
||||
// since a negative return value would be interpreted as an error.
|
||||
20 - nice.to_raw()
|
||||
20 - nice
|
||||
};
|
||||
|
||||
Ok(SyscallReturn::Return(highest_prio as _))
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
use ostd::{
|
||||
cpu::CpuSet,
|
||||
task::{Priority, Task, TaskOptions},
|
||||
task::{Task, TaskOptions},
|
||||
};
|
||||
|
||||
use super::{status::ThreadStatus, Thread};
|
||||
use crate::prelude::*;
|
||||
use crate::{prelude::*, sched::priority::Priority};
|
||||
|
||||
/// The inner data of a kernel thread
|
||||
pub struct KernelThread;
|
||||
@ -54,12 +54,17 @@ pub fn create_new_kernel_task(mut thread_options: ThreadOptions) -> Arc<Task> {
|
||||
let thread = {
|
||||
let kernel_thread = KernelThread;
|
||||
let status = ThreadStatus::Init;
|
||||
Arc::new(Thread::new(weak_task.clone(), kernel_thread, status))
|
||||
let priority = thread_options.priority;
|
||||
Arc::new(Thread::new(
|
||||
weak_task.clone(),
|
||||
kernel_thread,
|
||||
status,
|
||||
priority,
|
||||
))
|
||||
};
|
||||
|
||||
TaskOptions::new(thread_fn)
|
||||
.data(thread)
|
||||
.priority(thread_options.priority)
|
||||
.cpu_affinity(thread_options.cpu_affinity)
|
||||
.build()
|
||||
.unwrap()
|
||||
@ -81,7 +86,7 @@ impl ThreadOptions {
|
||||
let cpu_affinity = CpuSet::new_full();
|
||||
Self {
|
||||
func: Some(Box::new(func)),
|
||||
priority: Priority::normal(),
|
||||
priority: Priority::default(),
|
||||
cpu_affinity,
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ use core::sync::atomic::Ordering;
|
||||
use ostd::task::Task;
|
||||
|
||||
use self::status::{AtomicThreadStatus, ThreadStatus};
|
||||
use crate::prelude::*;
|
||||
use crate::{
|
||||
prelude::*,
|
||||
sched::priority::{AtomicPriority, Priority},
|
||||
};
|
||||
|
||||
pub mod exception;
|
||||
pub mod kernel_thread;
|
||||
@ -26,16 +29,25 @@ pub struct Thread {
|
||||
data: Box<dyn Send + Sync + Any>,
|
||||
|
||||
// mutable part
|
||||
/// Thread status
|
||||
status: AtomicThreadStatus,
|
||||
/// Thread priority
|
||||
priority: AtomicPriority,
|
||||
}
|
||||
|
||||
impl Thread {
|
||||
/// Never call these function directly
|
||||
pub fn new(task: Weak<Task>, data: impl Send + Sync + Any, status: ThreadStatus) -> Self {
|
||||
pub fn new(
|
||||
task: Weak<Task>,
|
||||
data: impl Send + Sync + Any,
|
||||
status: ThreadStatus,
|
||||
priority: Priority,
|
||||
) -> Self {
|
||||
Thread {
|
||||
task,
|
||||
data: Box::new(data),
|
||||
status: AtomicThreadStatus::new(status),
|
||||
priority: AtomicPriority::new(priority),
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,11 +91,26 @@ impl Thread {
|
||||
self.status.load(Ordering::Acquire)
|
||||
}
|
||||
|
||||
/// Updates the status with the `new` value.
|
||||
/// Updates the status with the new value.
|
||||
pub fn set_status(&self, new_status: ThreadStatus) {
|
||||
self.status.store(new_status, Ordering::Release);
|
||||
}
|
||||
|
||||
/// Returns the reference to the atomic priority.
|
||||
pub fn atomic_priority(&self) -> &AtomicPriority {
|
||||
&self.priority
|
||||
}
|
||||
|
||||
/// Returns the current priority.
|
||||
pub fn priority(&self) -> Priority {
|
||||
self.priority.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Updates the priority with the new value.
|
||||
pub fn set_priority(&self, new_priority: Priority) {
|
||||
self.priority.store(new_priority, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn yield_now() {
|
||||
Task::yield_now()
|
||||
}
|
||||
|
@ -2,14 +2,12 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use ostd::{
|
||||
cpu::CpuSet,
|
||||
task::{Priority, Task},
|
||||
};
|
||||
use ostd::{cpu::CpuSet, task::Task};
|
||||
|
||||
use super::worker_pool::WorkerPool;
|
||||
use crate::{
|
||||
prelude::*,
|
||||
sched::priority::{Priority, PriorityRange},
|
||||
thread::kernel_thread::{create_new_kernel_task, ThreadOptions},
|
||||
Thread,
|
||||
};
|
||||
@ -50,9 +48,10 @@ impl Worker {
|
||||
});
|
||||
let mut cpu_affinity = CpuSet::new_empty();
|
||||
cpu_affinity.add(bound_cpu);
|
||||
let mut priority = Priority::normal();
|
||||
let mut priority = Priority::default();
|
||||
if worker_pool.upgrade().unwrap().is_high_priority() {
|
||||
priority = Priority::high();
|
||||
// FIXME: remove the use of real-time priority.
|
||||
priority = Priority::new(PriorityRange::new(0));
|
||||
}
|
||||
let bound_task = create_new_kernel_task(
|
||||
ThreadOptions::new(task_fn)
|
||||
|
@ -7,15 +7,12 @@ use core::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use ostd::{
|
||||
cpu::CpuSet,
|
||||
sync::WaitQueue,
|
||||
task::{Priority, Task},
|
||||
};
|
||||
use ostd::{cpu::CpuSet, sync::WaitQueue, task::Task};
|
||||
|
||||
use super::{simple_scheduler::SimpleScheduler, worker::Worker, WorkItem, WorkPriority, WorkQueue};
|
||||
use crate::{
|
||||
prelude::*,
|
||||
sched::priority::{Priority, PriorityRange},
|
||||
thread::kernel_thread::{create_new_kernel_task, ThreadOptions},
|
||||
Thread,
|
||||
};
|
||||
@ -236,9 +233,13 @@ impl Monitor {
|
||||
current_monitor.run_monitor_loop();
|
||||
});
|
||||
let cpu_affinity = CpuSet::new_full();
|
||||
// FIXME: remove the use of real-time priority.
|
||||
// Logically all monitors should be of default normal priority.
|
||||
// This workaround is to make the monitor of high-priority worker pool
|
||||
// starvation-free under the current scheduling policy.
|
||||
let priority = match priority {
|
||||
WorkPriority::High => Priority::high(),
|
||||
WorkPriority::Normal => Priority::normal(),
|
||||
WorkPriority::High => Priority::new(PriorityRange::new(0)),
|
||||
WorkPriority::Normal => Priority::default(),
|
||||
};
|
||||
let bound_task = create_new_kernel_task(
|
||||
ThreadOptions::new(task_fn)
|
||||
|
@ -16,7 +16,7 @@ use processor::current_task;
|
||||
|
||||
pub use self::{
|
||||
preempt::{disable_preempt, DisabledPreemptGuard},
|
||||
scheduler::info::{AtomicCpuId, Priority, TaskScheduleInfo},
|
||||
scheduler::info::{AtomicCpuId, TaskScheduleInfo},
|
||||
};
|
||||
pub(crate) use crate::arch::task::{context_switch, TaskContext};
|
||||
use crate::{cpu::CpuSet, prelude::*, user::UserSpace};
|
||||
@ -124,7 +124,6 @@ pub struct TaskOptions {
|
||||
func: Option<Box<dyn Fn() + Send + Sync>>,
|
||||
data: Option<Box<dyn Any + Send + Sync>>,
|
||||
user_space: Option<Arc<UserSpace>>,
|
||||
priority: Priority,
|
||||
cpu_affinity: CpuSet,
|
||||
}
|
||||
|
||||
@ -138,7 +137,6 @@ impl TaskOptions {
|
||||
func: Some(Box::new(func)),
|
||||
data: None,
|
||||
user_space: None,
|
||||
priority: Priority::normal(),
|
||||
cpu_affinity: CpuSet::new_full(),
|
||||
}
|
||||
}
|
||||
@ -167,12 +165,6 @@ impl TaskOptions {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the priority of the task.
|
||||
pub fn priority(mut self, priority: Priority) -> Self {
|
||||
self.priority = priority;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the CPU affinity mask for the task.
|
||||
///
|
||||
/// The `cpu_affinity` parameter represents
|
||||
@ -220,7 +212,6 @@ impl TaskOptions {
|
||||
kstack,
|
||||
schedule_info: TaskScheduleInfo {
|
||||
cpu: AtomicCpuId::default(),
|
||||
priority: self.priority,
|
||||
cpu_affinity: self.cpu_affinity,
|
||||
},
|
||||
};
|
||||
|
@ -15,83 +15,12 @@ use crate::cpu::CpuSet;
|
||||
/// [existential types](https://github.com/rust-lang/rfcs/pull/2492) do not
|
||||
/// exist yet. So we decide to define them in OSTD.
|
||||
pub struct TaskScheduleInfo {
|
||||
/// Priority of the task.
|
||||
pub priority: Priority,
|
||||
/// The CPU that the task would like to be running on.
|
||||
pub cpu: AtomicCpuId,
|
||||
/// The CPUs that this task can run on.
|
||||
pub cpu_affinity: CpuSet,
|
||||
}
|
||||
|
||||
/// The priority of a real-time task.
|
||||
pub const REAL_TIME_TASK_PRIORITY: u16 = 100;
|
||||
|
||||
/// The priority of a task.
|
||||
///
|
||||
/// Similar to Linux, a larger value represents a lower priority,
|
||||
/// with a range of 0 to 139. Priorities ranging from 0 to 99 are considered real-time,
|
||||
/// while those ranging from 100 to 139 are considered normal.
|
||||
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
|
||||
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 <= Self::LOWEST);
|
||||
Self(val)
|
||||
}
|
||||
|
||||
/// Returns a `Priority` representing the lowest priority (139).
|
||||
pub const fn lowest() -> Self {
|
||||
Self::new(Self::LOWEST)
|
||||
}
|
||||
|
||||
/// Returns a `Priority` representing a low priority.
|
||||
pub const fn low() -> Self {
|
||||
Self::new(Self::LOW)
|
||||
}
|
||||
|
||||
/// Returns a `Priority` representing a normal priority.
|
||||
pub const fn normal() -> Self {
|
||||
Self::new(Self::NORMAL)
|
||||
}
|
||||
|
||||
/// Returns a `Priority` representing a high priority.
|
||||
pub const fn high() -> Self {
|
||||
Self::new(Self::HIGH)
|
||||
}
|
||||
|
||||
/// Returns a `Priority` representing the highest priority (0).
|
||||
pub const fn highest() -> Self {
|
||||
Self::new(Self::HIGHEST)
|
||||
}
|
||||
|
||||
/// Sets the value of the `Priority`.
|
||||
pub const fn set(&mut self, val: u16) {
|
||||
self.0 = val;
|
||||
}
|
||||
|
||||
/// Returns the value of the `Priority`.
|
||||
pub const fn get(self) -> u16 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Checks if the `Priority` is considered a real-time priority.
|
||||
pub const fn is_real_time(&self) -> bool {
|
||||
self.0 < REAL_TIME_TASK_PRIORITY
|
||||
}
|
||||
}
|
||||
|
||||
/// An atomic CPUID container.
|
||||
pub struct AtomicCpuId(AtomicU32);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user