Fix sys stats to reveal contexts in all CPU

This commit is contained in:
Wildan M
2026-04-06 13:34:20 +07:00
committed by Jeremy Soller
parent ee1260363c
commit 0ad905f26e
6 changed files with 84 additions and 61 deletions
+18 -2
View File
@@ -13,11 +13,13 @@ use syscall::PtraceFlags;
use crate::{
arch::device::ArchPercpuMisc,
context::{empty_cr3, memory::AddrSpaceWrapper, switch::ContextSwitchPercpu, ContextRef},
context::{
empty_cr3, memory::AddrSpaceWrapper, switch::ContextSwitchPercpu, ContextLock, ContextRef,
},
cpu_set::{LogicalCpuId, MAX_CPU_COUNT},
cpu_stats::{CpuStats, CpuStatsData},
ptrace::Session,
sync::{CleanLockToken, RwLock, L1},
sync::{CleanLockToken, LockToken, RwLock, L0, L1},
syscall::debug::SyscallDebugInfo,
};
@@ -70,6 +72,20 @@ pub fn get_all_stats() -> Vec<(LogicalCpuId, CpuStatsData)> {
res
}
/// Get copy of all cpu ref contexts
pub fn get_all_contexts(mut token: LockToken<'_, L1>) -> Vec<Arc<ContextLock>> {
let mut all_contexts = Vec::new();
for block in ALL_PERCPU_BLOCKS
.iter()
.filter_map(|block| unsafe { block.load(Ordering::Relaxed).as_ref() })
{
// TODO: Lock token violation, downgrade this to L2 later
let contexts = unsafe { &block.contexts.reupgradeable_read(token.token()) };
all_contexts.extend(contexts.iter().filter_map(|x| x.upgrade()));
}
all_contexts
}
// PercpuBlock::current() is implemented somewhere in the arch-specific modules
pub fn shootdown_tlb_ipi(target: Option<LogicalCpuId>) {
+3 -4
View File
@@ -1,7 +1,7 @@
use alloc::{string::String, vec::Vec};
use core::fmt::Write;
use crate::{context, sync::CleanLockToken, syscall::error::Result};
use crate::{context, percpu, sync::CleanLockToken, syscall::error::Result};
pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
let mut string = String::new();
@@ -9,9 +9,8 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
{
let mut rows = Vec::new();
{
let mut contexts = context::contexts(token.token());
let (contexts, mut token) = contexts.token_split();
for context_lock in contexts.iter().filter_map(|r| r.upgrade()) {
let contexts = percpu::get_all_contexts(token.downgrade());
for context_lock in contexts {
let context = context_lock.read(token.token());
rows.push((context.pid, context.name, context.status_reason));
}
+52 -41
View File
@@ -5,7 +5,7 @@ use alloc::{
};
use core::fmt::Write;
use crate::{context, sync::CleanLockToken, syscall::error::Result};
use crate::{context, percpu, sync::CleanLockToken, syscall::error::Result};
pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
let mut string = format!(
@@ -15,32 +15,59 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
let mut rows = Vec::new();
{
let mut contexts = context::contexts(token.token());
let (contexts, mut token) = contexts.token_split();
for context_ref in contexts.iter().filter_map(|r| r.upgrade()) {
let mut contexts = percpu::get_all_contexts(token.downgrade());
for context_ref in contexts {
let context = context_ref.read(token.token());
let addr_space = context.addr_space().map(|a| a.clone());
let affinity = context.sched_affinity.to_string();
let cpu_time_s = context.cpu_time / crate::time::NANOS_PER_SEC;
let cpu_time_ns = context.cpu_time % crate::time::NANOS_PER_SEC;
let mut memory = context.kfx.len();
if let Some(ref kstack) = context.kstack {
memory += kstack.len();
}
let (status, cpuid) = (context.status.clone(), context.cpu_id);
let (pid, euid, egid) = (context.pid, context.euid, context.egid);
let (running, is_awake) = (context.running, context.wake.is_some());
let name = context.name;
drop(context);
let heap = match addr_space {
Ok(addr_space) => {
let addr_space_guard = addr_space.acquire_read(token.downgrade());
let mut memory = 0;
// TODO: All user programs must have some grant in order for executable memory to even
// exist, but is this a good indicator of whether it is user or kernel?
let is_kernel = addr_space_guard.grants.is_empty();
for (_base, info) in addr_space_guard.grants.iter() {
// TODO: shared memory? wrap as method?
if matches!(info.provider, context::memory::Provider::Allocated { .. }) {
memory += info.page_count() * crate::memory::PAGE_SIZE;
}
}
Some((memory, is_kernel))
}
Err(_) => None,
};
let mut stat_string = String::new();
// TODO: All user programs must have some grant in order for executable memory to even
// exist, but is this a good indicator of whether it is user or kernel?
stat_string.push(match context.addr_space() {
Ok(addr_space) => {
// TODO: Commented out due Lock ordering violation
// if addr_space.acquire_read(token.downgrade()).grants.is_empty() {
// 'K'
// } else {
// 'U'
// }
'U'
stat_string.push(match heap {
Some((pages, is_kernel)) => {
if is_kernel {
'K'
} else {
'U'
}
}
_ => 'R',
});
match context.status {
match status {
context::Status::Runnable => {
stat_string.push('R');
}
context::Status::Blocked | context::Status::HardBlocked { .. } => {
if context.wake.is_some() {
if is_awake {
stat_string.push('S');
} else {
stat_string.push('B');
@@ -50,20 +77,16 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
stat_string.push('Z');
}
}
if context.running {
if running {
stat_string.push('+');
}
let cpu_string = match context.cpu_id {
let cpu_string = match cpuid {
Some(cpu_id) => {
format!("{cpu_id}")
}
_ => "?".to_owned(),
};
let affinity = context.sched_affinity.to_string();
let cpu_time_s = context.cpu_time / crate::time::NANOS_PER_SEC;
let cpu_time_ns = context.cpu_time % crate::time::NANOS_PER_SEC;
let cpu_time_string = format!(
"{:02}:{:02}:{:02}.{:02}",
cpu_time_s / 3600,
@@ -72,21 +95,9 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
cpu_time_ns / 10_000_000
);
let mut memory = context.kfx.len();
if let Some(ref kstack) = context.kstack {
memory += kstack.len();
if let Some((heap, _)) = heap {
memory += heap;
}
// TODO: Commented out due Lock ordering violation
/*
if let Ok(addr_space) = context.addr_space() {
for (_base, info) in addr_space.acquire_read(token.downgrade()).grants.iter() {
// TODO: method
if matches!(info.provider, context::memory::Provider::Allocated { .. }) {
memory += info.page_count() * PAGE_SIZE;
}
}
}
*/
let memory_string = if memory >= 1024 * 1024 * 1024 {
format!("{} GB", memory / 1024 / 1024 / 1024)
@@ -99,15 +110,15 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
};
rows.push((
context.pid,
context.euid,
context.egid,
pid,
euid,
egid,
stat_string,
cpu_string,
affinity,
cpu_time_string,
memory_string,
context.name,
name,
));
}
}
+2 -4
View File
@@ -4,7 +4,7 @@ use crate::{
memory::{Grant, PageSpan},
},
memory::PAGE_SIZE,
scheme,
percpu, scheme,
sync::CleanLockToken,
syscall::{
error::Result,
@@ -22,9 +22,7 @@ fn inner(fpath_user: UserSliceRw, token: &mut CleanLockToken) -> Result<Vec<u8>>
{
let mut rows = Vec::new();
{
let mut contexts = context::contexts(token.token());
let (contexts, mut token) = contexts.token_split();
for context_ref in contexts.iter().filter_map(|r| r.upgrade()) {
for context_ref in percpu::get_all_contexts(token.downgrade()) {
let mut current = context_ref.read(token.token());
let (context, mut token) = current.token_split();
rows.push((
+3 -6
View File
@@ -1,9 +1,9 @@
use core::fmt::Write as _;
use crate::{
context::{contexts, ContextRef, Status},
context::{ContextRef, Status},
cpu_stats::{get_context_switch_count, get_contexts_count, irq_counts},
percpu::get_all_stats,
percpu::{self, get_all_stats},
sync::CleanLockToken,
syscall::error::Result,
time::START,
@@ -76,11 +76,8 @@ fn get_contexts_stats(token: &mut CleanLockToken) -> (u64, u64) {
let mut running = 0;
let mut blocked = 0;
let mut contexts = contexts(token.token());
let (contexts, mut token) = contexts.token_split();
let statuses = contexts
let statuses = percpu::get_all_contexts(token.downgrade())
.iter()
.filter_map(ContextRef::upgrade)
.map(|context| context.read(token.token()).status.clone())
.collect::<Vec<_>>();
+6 -4
View File
@@ -1,7 +1,11 @@
use alloc::{string::String, vec::Vec};
use core::fmt::Write;
use crate::{context, sync::CleanLockToken, syscall, syscall::error::Result};
use crate::{
context, percpu,
sync::CleanLockToken,
syscall::{self, error::Result},
};
pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
let mut string = String::new();
@@ -9,9 +13,7 @@ pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
{
let mut rows = Vec::new();
{
let mut contexts = context::contexts(token.token());
let (contexts, mut token) = contexts.token_split();
for context_ref in contexts.iter().filter_map(|r| r.upgrade()) {
for context_ref in percpu::get_all_contexts(token.downgrade()) {
let context = context_ref.read(token.token());
rows.push((context.pid, context.name, context.current_syscall()));
}