sysfs: basic scheduler stats
This commit is contained in:
parent
8adc011281
commit
becbf2aea1
@ -6,8 +6,6 @@ build = "build.rs"
|
||||
authors = ["Mark Poliakov <mark@alnyan.me>"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[profile.dev.package.tock-registers]
|
||||
opt-level = 3
|
||||
|
||||
[dependencies]
|
||||
abi-lib = { path = "../lib/abi-lib" }
|
||||
|
@ -34,6 +34,3 @@ version = "0.7.2"
|
||||
git = "https://git.alnyan.me/yggdrasil/yggdrasil-elf.git"
|
||||
default-features = false
|
||||
features = ["no_std_stream"]
|
||||
|
||||
[profile.dev]
|
||||
rustflags = ["-Clink-dead-code=yes -Zexport-executable-symbols -Cprefer-dynamic"]
|
||||
|
@ -1,4 +1,8 @@
|
||||
use core::cell::Cell;
|
||||
use core::{
|
||||
cell::Cell,
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use crossbeam_queue::SegQueue;
|
||||
@ -6,6 +10,7 @@ use kernel_arch::{
|
||||
task::{Scheduler, TaskContext},
|
||||
Architecture, ArchitectureImpl, CpuImpl,
|
||||
};
|
||||
use libk_device::monotonic_timestamp;
|
||||
use libk_util::{sync::IrqGuard, OneTimeInit};
|
||||
|
||||
use crate::task::{thread::Thread, TaskContextImpl, ThreadId, ThreadState};
|
||||
@ -15,6 +20,17 @@ pub struct CpuQueue {
|
||||
queue: SegQueue<ThreadId>,
|
||||
index: usize,
|
||||
idle: Cell<TaskContextImpl>,
|
||||
|
||||
stats: SchedulerStats,
|
||||
last_stats_measure: Cell<Option<Duration>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SchedulerStats {
|
||||
pub idle: AtomicU64,
|
||||
pub user: AtomicU64,
|
||||
pub kernel: AtomicU64,
|
||||
pub total: AtomicU64,
|
||||
}
|
||||
|
||||
static QUEUES: OneTimeInit<Vec<CpuQueue>> = OneTimeInit::new();
|
||||
@ -32,6 +48,9 @@ impl CpuQueue {
|
||||
queue: SegQueue::new(),
|
||||
index,
|
||||
idle: Cell::new(idle),
|
||||
|
||||
stats: SchedulerStats::default(),
|
||||
last_stats_measure: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +105,23 @@ impl CpuQueue {
|
||||
|
||||
(None, None)
|
||||
}
|
||||
|
||||
fn update_stats(&self, delta: Duration, current: Option<&Arc<Thread>>) {
|
||||
let counter = if let Some(current) = current {
|
||||
if current.is_user() {
|
||||
&self.stats.user
|
||||
} else {
|
||||
&self.stats.kernel
|
||||
}
|
||||
} else {
|
||||
&self.stats.idle
|
||||
};
|
||||
|
||||
let t = delta.as_millis() as u64;
|
||||
|
||||
self.stats.total.fetch_add(t, Ordering::Relaxed);
|
||||
counter.fetch_add(t, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheduler for CpuQueue {
|
||||
@ -127,6 +163,13 @@ impl Scheduler for CpuQueue {
|
||||
let current_id = cpu.current_thread_id();
|
||||
let current = current_id.and_then(Thread::get);
|
||||
|
||||
let t = monotonic_timestamp().unwrap();
|
||||
if let Some(t0) = self.last_stats_measure.get() {
|
||||
let dt = t - t0;
|
||||
self.update_stats(dt, current.as_ref());
|
||||
}
|
||||
self.last_stats_measure.set(Some(t));
|
||||
|
||||
let drop_current = if let Some(current) = current.as_ref() {
|
||||
let mut sched = current.sched.lock();
|
||||
|
||||
@ -196,6 +239,10 @@ impl Scheduler for CpuQueue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stats(index: usize) -> &'static SchedulerStats {
|
||||
&QUEUES.get()[index].stats
|
||||
}
|
||||
|
||||
/// Initializes the global queue list
|
||||
pub fn init_queues(queues: Vec<CpuQueue>) {
|
||||
QUEUES.init(queues);
|
||||
|
@ -173,6 +173,9 @@ impl Thread {
|
||||
}
|
||||
|
||||
// Get/Set
|
||||
pub fn is_user(&self) -> bool {
|
||||
self.id.is_user()
|
||||
}
|
||||
|
||||
/// Updates the thread affinity to run on a specific set of CPUs
|
||||
pub fn set_affinity(&self, affinity: u64) {
|
||||
|
@ -1,10 +1,16 @@
|
||||
//! "System" filesystem implementation
|
||||
|
||||
use abi::error::Error;
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use abi::{error::Error, io::OpenOptions};
|
||||
use alloc::{format, string::String, sync::Arc};
|
||||
use git_version::git_version;
|
||||
use libk::vfs::{
|
||||
impls::{const_value_node, mdir, read_fn_node, ReadOnlyFnValueNode},
|
||||
NodeRef,
|
||||
use libk::{
|
||||
task::{cpu_count, process::Process, sched},
|
||||
vfs::{
|
||||
impls::{const_value_node, mdir, read_fn_node, ReadOnlyFnValueNode},
|
||||
CommonImpl, InstanceData, NodeRef, RegularImpl,
|
||||
},
|
||||
};
|
||||
use libk_mm::phys;
|
||||
use libk_util::OneTimeInit;
|
||||
@ -22,6 +28,21 @@ fn read_kernel_log(pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
|
||||
Ok(debug::RING_LOGGER_SINK.read(pos as usize, buffer))
|
||||
}
|
||||
|
||||
fn sched_stats() -> String {
|
||||
let mut res = String::new();
|
||||
for i in 0..cpu_count() {
|
||||
let stats = sched::stats(i);
|
||||
res.push_str(&format!(
|
||||
"{} {} {} {}",
|
||||
stats.idle.load(Ordering::Relaxed),
|
||||
stats.user.load(Ordering::Relaxed),
|
||||
stats.kernel.load(Ordering::Relaxed),
|
||||
stats.total.load(Ordering::Relaxed)
|
||||
));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
/// Sets up the entries within the filesystem
|
||||
pub fn init() {
|
||||
let d_kernel = mdir([
|
||||
@ -29,6 +50,10 @@ pub fn init() {
|
||||
("rev", const_value_node(git_version!())),
|
||||
("log", read_fn_node(read_kernel_log)),
|
||||
]);
|
||||
let d_proc = mdir([(
|
||||
"sched_stats",
|
||||
ReadOnlyFnValueNode::new_node(|| Ok(sched_stats())),
|
||||
)]);
|
||||
let d_mem_phys = mdir([
|
||||
(
|
||||
"total_pages",
|
||||
@ -47,6 +72,7 @@ pub fn init() {
|
||||
let root = mdir([
|
||||
("kernel", d_kernel),
|
||||
("mem", d_mem),
|
||||
("proc", d_proc),
|
||||
("arch", const_value_node(util::arch_str())),
|
||||
]);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
collections::HashMap,
|
||||
fs::{File, OpenOptions},
|
||||
io::{Read, Seek, SeekFrom, Write},
|
||||
ops::Range,
|
||||
|
Loading…
x
Reference in New Issue
Block a user