mirror of
https://github.com/redox-os/kernel.git
synced 2026-09-09 00:07:34 +08:00
Avoid fetch_add for context switch count.
Together with the previous commit, this reduces base IPC latency by 1%.
This commit is contained in:
+5
-2
@@ -15,6 +15,7 @@ use crate::{
|
||||
switch::{BASE_SLICE_TICKS, NANOS_PER_TICK, SCALE, SCHED_PRIO_TO_WEIGHT, TICK_INTERVAL},
|
||||
},
|
||||
cpu_set::{LogicalCpuId, LogicalCpuSet},
|
||||
cpu_stats::CpuStatsData,
|
||||
ipi::{ipi, IpiKind, IpiTarget},
|
||||
memory::{RmmA, RmmArch, TableKind},
|
||||
percpu::PercpuBlock,
|
||||
@@ -385,10 +386,11 @@ impl Drop for PreemptGuardL2<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_contexts_stats(token: &mut CleanLockToken) -> (usize, usize, usize) {
|
||||
pub fn get_contexts_stats(token: &mut CleanLockToken) -> (usize, usize, usize, usize) {
|
||||
let alive = contexts(token.downgrade()).len();
|
||||
|
||||
let mut running = 0;
|
||||
let mut switches = 0;
|
||||
|
||||
for i in 0..crate::cpu_count() {
|
||||
if let Some(percpu) = unsafe {
|
||||
@@ -397,10 +399,11 @@ pub fn get_contexts_stats(token: &mut CleanLockToken) -> (usize, usize, usize) {
|
||||
.as_ref()
|
||||
} {
|
||||
running += percpu.switch_internals.run_queue.lock().queue.len();
|
||||
switches += CpuStatsData::from(&percpu.stats).context_switches as usize;
|
||||
}
|
||||
}
|
||||
|
||||
let blocked = alive.saturating_sub(running);
|
||||
|
||||
(alive, running, blocked)
|
||||
(alive, running, blocked, switches)
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
let switch_time = crate::time::monotonic(token);
|
||||
|
||||
let percpu = PercpuBlock::current();
|
||||
cpu_stats::add_context_switch();
|
||||
percpu.stats.add_context_switch();
|
||||
|
||||
//set PIT Interrupt counter to 0, giving each process same amount of PIT ticks
|
||||
percpu.switch_internals.pit_ticks.set(0);
|
||||
|
||||
+19
-20
@@ -4,9 +4,6 @@ use core::{
|
||||
sync::atomic::{AtomicU64, AtomicU8, AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
// Note: Using AtomicUsize rather than AtomicU64 as 32bit x86 doesn't support the latter
|
||||
/// The number of times (overall) where a CPU switched from one context to another.
|
||||
static CONTEXT_SWITCH_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
/// Number of times each Interrupt happened.
|
||||
// TODO: isn't this already tracked by the irq scheme?
|
||||
static IRQ_COUNT: [AtomicUsize; 256] = [const { AtomicUsize::new(0) }; 256];
|
||||
@@ -42,6 +39,8 @@ pub struct CpuStats {
|
||||
irq: AtomicU64,
|
||||
/// Current state of the CPU
|
||||
state: AtomicU8,
|
||||
/// The number of times (overall) where a CPU switched from one context to another.
|
||||
context_switches: AtomicU64,
|
||||
}
|
||||
|
||||
impl CpuStats {
|
||||
@@ -53,6 +52,7 @@ impl CpuStats {
|
||||
idle: AtomicU64::new(0),
|
||||
irq: AtomicU64::new(0),
|
||||
state: AtomicU8::new(0),
|
||||
context_switches: AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,13 +68,12 @@ pub struct CpuStatsData {
|
||||
pub idle: u64,
|
||||
/// Number of times the CPU handled an interrupt
|
||||
pub irq: u64,
|
||||
/// Number of context switches on this CPU
|
||||
pub context_switches: u64,
|
||||
}
|
||||
|
||||
impl CpuStats {
|
||||
/// Set the CPU's current state
|
||||
///
|
||||
/// # Parameters
|
||||
/// * `new_state` - The state of the CPU for the following ticks.
|
||||
/// Set the CPU's current state for the following ticks.
|
||||
#[inline]
|
||||
pub fn set_state(&self, new_state: CpuState) {
|
||||
self.state.store(new_state as u8, Ordering::Relaxed);
|
||||
@@ -116,14 +115,24 @@ impl CpuStats {
|
||||
self.irq
|
||||
.store(self.irq.load(Ordering::Relaxed) + 1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Add a context switch to the count.
|
||||
#[inline]
|
||||
pub fn add_context_switch(&self) {
|
||||
// Again this is percpu, so fetch_add is unnecessary.
|
||||
self.context_switches.store(
|
||||
self.context_switches.load(Ordering::Relaxed) + 1,
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CpuStatsData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} {} {} {} {}",
|
||||
self.user, self.nice, self.kernel, self.idle, self.irq,
|
||||
"{} {} {} {} {} {}",
|
||||
self.user, self.nice, self.kernel, self.idle, self.irq, self.context_switches
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -136,21 +145,11 @@ impl From<&CpuStats> for CpuStatsData {
|
||||
kernel: val.kernel.load(Ordering::Relaxed),
|
||||
idle: val.idle.load(Ordering::Relaxed),
|
||||
irq: val.irq.load(Ordering::Relaxed),
|
||||
context_switches: val.context_switches.load(Ordering::Relaxed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a context switch to the count.
|
||||
#[inline]
|
||||
pub fn add_context_switch() {
|
||||
CONTEXT_SWITCH_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Get the number of context switches.
|
||||
pub fn get_context_switch_count() -> usize {
|
||||
CONTEXT_SWITCH_COUNT.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Add a context creation to the count.
|
||||
#[inline]
|
||||
pub fn add_context() {
|
||||
|
||||
@@ -2,7 +2,7 @@ use core::fmt::Write as _;
|
||||
|
||||
use crate::{
|
||||
context::get_contexts_stats,
|
||||
cpu_stats::{get_context_switch_count, get_contexts_count, irq_counts},
|
||||
cpu_stats::{get_contexts_count, irq_counts},
|
||||
event::get_event_stat,
|
||||
percpu::get_all_stats,
|
||||
sync::CleanLockToken,
|
||||
@@ -15,7 +15,8 @@ use alloc::{string::String, vec::Vec};
|
||||
pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
|
||||
let start_time_sec = *START.lock(token.token()) / 1_000_000_000;
|
||||
|
||||
let (contexts_alive, contexts_running, contexts_blocked) = get_contexts_stats(token);
|
||||
let (contexts_alive, contexts_running, contexts_blocked, context_switches) =
|
||||
get_contexts_stats(token);
|
||||
let (event_keys, event_subs) = get_event_stat(token);
|
||||
let (futex_keys, futex_subs) = get_futex_stat(token);
|
||||
let pipe_subs = crate::scheme::pipe::get_pipe_stat(token);
|
||||
@@ -36,7 +37,7 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
|
||||
timeout_subscribers: {timeout_subs}\n",
|
||||
get_cpu_stats(),
|
||||
get_irq_stats(),
|
||||
get_context_switch_count(),
|
||||
context_switches,
|
||||
get_contexts_count(),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user