Finish the work on separating timers

This commit is contained in:
Akshit Gaur
2026-07-16 13:48:54 +00:00
committed by Jeremy Soller
parent ee4a5602a6
commit f5fe18b23c
7 changed files with 83 additions and 27 deletions
-1
View File
@@ -279,7 +279,6 @@ impl Context {
pub fn unblock_no_ipi(&mut self) -> bool {
if self.status.is_soft_blocked() {
self.status = Status::Runnable;
self.wake = None;
self.status_reason = "";
true
+32 -2
View File
@@ -9,13 +9,17 @@ use alloc::{
use core::{cmp::Reverse, num::NonZeroUsize, ops::Deref};
use crate::{
context::memory::AddrSpaceWrapper,
context::{
memory::AddrSpaceWrapper,
switch::{BASE_SLICE_TICKS, NANOS_PER_TICK, SCALE, SCHED_PRIO_TO_WEIGHT, TICK_INTERVAL},
},
cpu_set::LogicalCpuSet,
ipi::{ipi, IpiKind, IpiTarget},
memory::{RmmA, RmmArch, TableKind},
percpu::PercpuBlock,
sync::{
ArcRwLockWriteGuard, CleanLockToken, LockToken, Mutex, MutexGuard, RwLock, RwLockReadGuard,
RwLockWriteGuard, L0, L1, L2, L4,
RwLockWriteGuard, L0, L1, L2, L3, L4,
},
syscall::error::Result,
};
@@ -135,6 +139,32 @@ pub fn run_contexts_try(token: LockToken<'_, L0>) -> Option<MutexGuard<'_, L1, R
RUN_CONTEXTS.try_lock(token)
}
pub fn unblock_context(context_lock: &Arc<ContextLock>, token: &mut LockToken<'_, L3>) -> bool {
let was_blocked = {
let mut guard = context_lock.write(token.token());
if !guard.unblock_no_ipi() {
return false;
}
true
};
let percpu: &PercpuBlock = PercpuBlock::current();
let weak = WeakContextRef(Arc::downgrade(context_lock));
let cpu_id = context_lock.write(token.token()).cpu_id;
percpu.switch_internals.wakeup_list.borrow_mut().push(weak);
if let Some(cpu_id) = cpu_id
&& cpu_id != crate::cpu_id()
{
ipi(IpiKind::Wakeup, IpiTarget::Other);
}
true
}
pub fn init(token: &mut CleanLockToken) {
let owner = None; // kmain not owned by any fd
let mut context = Context::new(owner).expect("failed to create kmain context");
+33 -8
View File
@@ -13,7 +13,7 @@ use crate::{
percpu::PercpuBlock,
sync::{ArcRwLockWriteGuard, CleanLockToken, L4},
};
use alloc::sync::Arc;
use alloc::{sync::Arc, vec::Vec};
use core::{
cell::{Cell, RefCell},
cmp::Reverse,
@@ -32,16 +32,16 @@ enum UpdateResult {
}
// A simple geometric series where value[i] ~= value[i + 1] * 1.25
const SCHED_PRIO_TO_WEIGHT: [usize; 40] = [
pub const SCHED_PRIO_TO_WEIGHT: [usize; 40] = [
88761, 71755, 56483, 46273, 36291, 29154, 23254, 18705, 14949, 11916, 9548, 7620, 6100, 4904,
3906, 3121, 2501, 1991, 1586, 1277, 1024, 820, 655, 526, 423, 335, 272, 215, 172, 137, 110, 87,
70, 56, 45, 36, 29, 23, 18, 15,
];
const SCALE: u128 = 1 << 40;
const TICK_INTERVAL: u64 = 3; // Approx 6.75 ms
const BASE_SLICE_TICKS: u64 = TICK_INTERVAL * 3; // Approx 20.25 ms
const NANOS_PER_TICK: u128 = 2_250_000; // 2.25 ms
pub const SCALE: u128 = 1 << 40;
pub const TICK_INTERVAL: u64 = 3; // Approx 6.75 ms
pub const BASE_SLICE_TICKS: u64 = TICK_INTERVAL * 3; // Approx 20.25 ms
pub const NANOS_PER_TICK: u128 = 2_250_000; // 2.25 ms
/// Determines if a given context is eligible to be scheduled on a given CPU (in
/// principle, the current CPU).
@@ -190,6 +190,8 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
let mut wakeups = wakeup_contexts(token);
let mut push_idle: SmallVec<[WeakContextRef; 16]> = SmallVec::new();
// These timers coukd have expired
let mut timers: SmallVec<[(u128, WeakContextRef); 16]> = SmallVec::new();
if let Some(mut run_contexts) = run_contexts_try(token.token()) {
// Pop Timers
while let Some((wake, _)) = run_contexts.timers.first() {
@@ -197,12 +199,31 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
break;
}
if let Some((_, context_ref)) = run_contexts.timers.pop_first() {
wakeups.push(context_ref);
if let Some(entry) = run_contexts.timers.pop_first() {
timers.push(entry);
}
}
}
for (wake, context_ref) in timers {
let Some(context_lock) = context_ref.upgrade() else {
continue;
};
let guard = context_lock.read(token.token());
if guard.status.is_soft_blocked() && guard.wake == Some(wake) {
wakeups.push(context_ref);
}
}
// Drain from percpu
let mut percpu_wake = percpu.switch_internals.wakeup_list.replace(Vec::new());
if percpu_wake.len() > 0 {
for context_ref in percpu_wake.iter() {
wakeups.push(context_ref.clone());
}
}
if wakeups.len() > 0 {
let mut run_contexts = run_contexts(token.token());
for context_ref in wakeups {
@@ -697,6 +718,9 @@ pub struct ContextSwitchPercpu {
/// The idle process.
idle_ctxt: RefCell<Option<Arc<ContextLock>>>,
pub(crate) being_sigkilled: Cell<bool>,
// wakeups
pub(crate) wakeup_list: RefCell<Vec<WeakContextRef>>,
}
impl ContextSwitchPercpu {
@@ -708,6 +732,7 @@ impl ContextSwitchPercpu {
current_ctxt: RefCell::new(None),
idle_ctxt: RefCell::new(None),
being_sigkilled: Cell::new(false),
wakeup_list: RefCell::new(Vec::new()),
#[cfg(feature = "profiling")]
current_dbg_id: core::sync::atomic::AtomicU32::new(!0),
+11 -9
View File
@@ -4,7 +4,7 @@ use crate::{
context::{HardBlockedReason, LockedFdTbl, SignalState},
file::InternalFlags,
memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan, UnmapVec},
Context, ContextLock, Status,
unblock_context, Context, ContextLock, Status,
},
memory::{Page, VirtualAddress, PAGE_SIZE},
ptrace,
@@ -1248,8 +1248,7 @@ impl ContextHandle {
Ok(size_of::<usize>())
}
ContextVerb::Interrupt => {
let mut guard = context.write(token.token());
guard.unblock();
unblock_context(&context, &mut token.token().downgrade());
Ok(size_of::<usize>())
}
ContextVerb::ForceKill => {
@@ -1278,13 +1277,16 @@ impl ContextHandle {
}
crate::syscall::exit_this_context(None, token);
} else {
let mut ctxt = context.write(token.token());
//trace!("FORCEKILL NONSELF={} {}, SELF={}", ctxt.debug_id, ctxt.pid, context::current().read().debug_id);
if ctxt.status.is_dead() {
return Ok(size_of::<usize>());
{
let mut ctxt = context.write(token.token());
//trace!("FORCEKILL NONSELF={} {}, SELF={}", ctxt.debug_id, ctxt.pid, context::current().read().debug_id);
if ctxt.status.is_dead() {
return Ok(size_of::<usize>());
}
ctxt.status = context::Status::Runnable;
ctxt.being_sigkilled = true;
}
ctxt.status = context::Status::Runnable;
ctxt.being_sigkilled = true;
unblock_context(&context, &mut token.token().downgrade());
Ok(size_of::<usize>())
}
}
+2 -2
View File
@@ -22,7 +22,7 @@ use crate::{
handle_notify_files, AddrSpace, AddrSpaceWrapper, BorrowedFmapSource, Grant,
GrantFileRef, MmapMode, PageSpan, UnmapVec, DANGLING,
},
BorrowedHtBuf, ContextLock, PreemptGuard, PreemptGuardL1, Status,
unblock_context, BorrowedHtBuf, ContextLock, PreemptGuard, PreemptGuardL1, Status,
},
event,
memory::{Frame, Page, VirtualAddress, PAGE_SIZE},
@@ -956,7 +956,7 @@ impl UserInner {
match context.upgrade() {
Some(context) => {
*o = State::Responded(response);
context.write(lock_token.token()).unblock();
unblock_context(&context, &mut lock_token.token().downgrade());
}
_ => {
states.remove(tag as usize);
+3 -3
View File
@@ -6,7 +6,7 @@ use alloc::{
};
use crate::{
context::{self, ContextLock, PreemptGuardL2},
context::{self, unblock_context, ContextLock, PreemptGuardL2},
sync::{CleanLockToken, LockToken, Mutex, L1, L2, L3},
};
@@ -33,7 +33,7 @@ impl WaitCondition {
let len = contexts.len();
while let Some(context_weak) = contexts.pop() {
if let Some(context_ref) = context_weak.upgrade() {
context_ref.write(token.token()).unblock();
unblock_context(&context_ref, &mut token.token());
}
}
len
@@ -46,7 +46,7 @@ impl WaitCondition {
let len = contexts.len();
for context_weak in contexts.iter() {
if let Some(context_ref) = context_weak.upgrade() {
context_ref.write(token.token()).unblock();
unblock_context(&context_ref, &mut token.token());
}
}
len
+2 -2
View File
@@ -15,7 +15,7 @@ use crate::{
context::{
self,
memory::{AddrSpace, AddrSpaceWrapper},
ContextLock,
unblock_context, ContextLock,
},
memory::{Page, PhysicalAddress, VirtualAddress},
sync::{CleanLockToken, Mutex, L1},
@@ -214,7 +214,7 @@ pub fn futex(
continue;
}
if let Some(ctx) = futex.context_lock.upgrade() {
ctx.write(token.token()).unblock();
unblock_context(&ctx, &mut token.token().downgrade());
}
futexes.swap_remove(i);
woken += 1;