Reduce the held time of scheduling policy lock

This commit is contained in:
js2xxx
2024-12-04 15:22:13 +00:00
committed by Tate, Hongliang Tian
parent ea953209ff
commit 364d6af7c8
6 changed files with 264 additions and 141 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use alloc::{collections::binary_heap::BinaryHeap, sync::Arc};
use alloc::collections::binary_heap::BinaryHeap;
use core::{
cmp::{self, Reverse},
sync::atomic::{AtomicU64, Ordering::*},
@ -13,12 +13,9 @@ use ostd::{
use super::{
time::{base_slice_clocks, min_period_clocks},
CurrentRuntime, SchedAttr, SchedClassRq,
};
use crate::{
sched::priority::{Nice, NiceRange},
thread::Thread,
CurrentRuntime, SchedAttr, SchedClassRq, SchedEntity,
};
use crate::sched::priority::{Nice, NiceRange};
const WEIGHT_0: u64 = 1024;
pub const fn nice_to_weight(nice: Nice) -> u64 {
@ -120,7 +117,7 @@ impl FairAttr {
///
/// This structure is used to provide the capability for keying in the
/// run queue implemented by `BTreeSet` in the `FairClassRq`.
struct FairQueueItem(Arc<Thread>);
struct FairQueueItem(SchedEntity);
impl core::fmt::Debug for FairQueueItem {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
@ -130,7 +127,7 @@ impl core::fmt::Debug for FairQueueItem {
impl FairQueueItem {
fn key(&self) -> u64 {
self.0.sched_attr().fair.vruntime.load(Relaxed)
self.0 .1.sched_attr().fair.vruntime.load(Relaxed)
}
}
@ -165,7 +162,7 @@ pub(super) struct FairClassRq {
#[allow(unused)]
cpu: CpuId,
/// The ready-to-run threads.
threads: BinaryHeap<Reverse<FairQueueItem>>,
entities: BinaryHeap<Reverse<FairQueueItem>>,
/// The minimum of vruntime in the run queue. Serves as the initial
/// value of newly-enqueued threads.
min_vruntime: u64,
@ -176,7 +173,7 @@ impl FairClassRq {
pub fn new(cpu: CpuId) -> Self {
Self {
cpu,
threads: BinaryHeap::new(),
entities: BinaryHeap::new(),
min_vruntime: 0,
total_weight: 0,
}
@ -201,13 +198,13 @@ impl FairClassRq {
// `+ 1` means including the current running thread.
let period_single_cpu =
(base_slice_clks * (self.threads.len() + 1) as u64).max(min_period_clks);
(base_slice_clks * (self.entities.len() + 1) as u64).max(min_period_clks);
period_single_cpu * u64::from((1 + num_cpus()).ilog2())
}
/// The virtual time slice for each thread in the run queue, measured in vruntime clocks.
fn vtime_slice(&self) -> u64 {
self.period() / (self.threads.len() + 1) as u64
self.period() / (self.entities.len() + 1) as u64
}
/// The time slice for each thread in the run queue, measured in sched clocks.
@ -217,8 +214,8 @@ impl FairClassRq {
}
impl SchedClassRq for FairClassRq {
fn enqueue(&mut self, thread: Arc<Thread>, flags: Option<EnqueueFlags>) {
let fair_attr = &thread.sched_attr().fair;
fn enqueue(&mut self, entity: SchedEntity, flags: Option<EnqueueFlags>) {
let fair_attr = &entity.1.sched_attr().fair;
let vruntime = match flags {
Some(EnqueueFlags::Spawn) => self.min_vruntime + self.vtime_slice(),
_ => self.min_vruntime,
@ -226,23 +223,23 @@ impl SchedClassRq for FairClassRq {
fair_attr.vruntime.fetch_max(vruntime, Relaxed);
self.total_weight += fair_attr.weight.load(Relaxed);
self.threads.push(Reverse(FairQueueItem(thread)));
self.entities.push(Reverse(FairQueueItem(entity)));
}
fn len(&mut self) -> usize {
self.threads.len()
self.entities.len()
}
fn is_empty(&mut self) -> bool {
self.threads.is_empty()
self.entities.is_empty()
}
fn pick_next(&mut self) -> Option<Arc<Thread>> {
let Reverse(FairQueueItem(thread)) = self.threads.pop()?;
fn pick_next(&mut self) -> Option<SchedEntity> {
let Reverse(FairQueueItem(entity)) = self.entities.pop()?;
self.total_weight -= thread.sched_attr().fair.weight.load(Relaxed);
self.total_weight -= entity.1.sched_attr().fair.weight.load(Relaxed);
Some(thread)
Some(entity)
}
fn update_current(
@ -255,7 +252,7 @@ impl SchedClassRq for FairClassRq {
UpdateFlags::Yield => true,
UpdateFlags::Tick | UpdateFlags::Wait => {
let (vruntime, weight) = attr.fair.update_vruntime(rt.delta);
self.min_vruntime = match self.threads.peek() {
self.min_vruntime = match self.entities.peek() {
Some(Reverse(leftmost)) => vruntime.min(leftmost.key()),
None => vruntime,
};