feature: statistics for phys mem module
This commit is contained in:
@@ -20,6 +20,9 @@ endif
|
||||
|
||||
CARGO_BUILD_OPTS=$(CARGO_COMMON_OPTS) \
|
||||
--target=../etc/$(ARCH)-$(MACH).json
|
||||
ifeq ($(VERBOSE),1)
|
||||
CARGO_BUILD_OPTS+=--features verbose
|
||||
endif
|
||||
ifneq ($(MACH),)
|
||||
CARGO_BUILD_OPTS+=--features mach_$(MACH)
|
||||
endif
|
||||
|
||||
@@ -61,6 +61,14 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
let ring = self.ring();
|
||||
let config = ring.config.lock();
|
||||
|
||||
if byte == b'@' {
|
||||
use crate::mem::phys;
|
||||
let stat = phys::statistics();
|
||||
debugln!("Physical memory stats:");
|
||||
debugln!("{:#?}", stat);
|
||||
return;
|
||||
}
|
||||
|
||||
if byte == b'\r' && config.iflag.contains(TermiosIflag::ICRNL) {
|
||||
byte = b'\n';
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{PageInfo, PageUsage};
|
||||
use super::{PageInfo, PageUsage, PageStatistics};
|
||||
use crate::mem::{memcpy, memset, virtualize, PAGE_SIZE};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use core::mem;
|
||||
@@ -10,10 +10,12 @@ pub unsafe trait Manager {
|
||||
fn free_page(&mut self, page: usize) -> Result<(), Errno>;
|
||||
fn copy_cow_page(&mut self, src: usize) -> Result<usize, Errno>;
|
||||
fn fork_page(&mut self, src: usize) -> Result<usize, Errno>;
|
||||
fn statistics(&self) -> PageStatistics;
|
||||
// TODO status()
|
||||
}
|
||||
pub struct SimpleManager {
|
||||
pages: &'static mut [PageInfo],
|
||||
stats: PageStatistics,
|
||||
base_index: usize,
|
||||
}
|
||||
impl SimpleManager {
|
||||
@@ -32,6 +34,14 @@ impl SimpleManager {
|
||||
}
|
||||
Self {
|
||||
base_index: base / PAGE_SIZE,
|
||||
stats: PageStatistics {
|
||||
available: 0,
|
||||
kernel: 0,
|
||||
kernel_heap: 0,
|
||||
paging: 0,
|
||||
user_private: 0,
|
||||
filesystem: 0
|
||||
},
|
||||
pages,
|
||||
}
|
||||
}
|
||||
@@ -39,6 +49,7 @@ impl SimpleManager {
|
||||
let page = &mut self.pages[self.page_index(addr)];
|
||||
assert!(page.refcount == 0 && page.usage == PageUsage::Reserved);
|
||||
page.usage = PageUsage::Available;
|
||||
self.stats.available += 1;
|
||||
}
|
||||
|
||||
fn page_index(&self, page: usize) -> usize {
|
||||
@@ -56,11 +67,41 @@ impl SimpleManager {
|
||||
}
|
||||
Err(Errno::OutOfMemory)
|
||||
}
|
||||
|
||||
fn update_stats_alloc(&mut self, pu: PageUsage, count: usize) {
|
||||
let field = match pu {
|
||||
PageUsage::Kernel => &mut self.stats.kernel,
|
||||
PageUsage::KernelHeap => &mut self.stats.kernel_heap,
|
||||
PageUsage::Paging => &mut self.stats.paging,
|
||||
PageUsage::UserPrivate => &mut self.stats.user_private,
|
||||
PageUsage::Filesystem => &mut self.stats.filesystem,
|
||||
_ => panic!("TODO {:?}", pu),
|
||||
};
|
||||
*field += count;
|
||||
self.stats.available -= count;
|
||||
}
|
||||
|
||||
fn update_stats_free(&mut self, pu: PageUsage, count: usize) {
|
||||
let field = match pu {
|
||||
PageUsage::Kernel => &mut self.stats.kernel,
|
||||
PageUsage::KernelHeap => &mut self.stats.kernel_heap,
|
||||
PageUsage::Paging => &mut self.stats.paging,
|
||||
PageUsage::UserPrivate => &mut self.stats.user_private,
|
||||
PageUsage::Filesystem => &mut self.stats.filesystem,
|
||||
_ => panic!("TODO {:?}", pu),
|
||||
};
|
||||
*field -= count;
|
||||
self.stats.available += count;
|
||||
}
|
||||
}
|
||||
unsafe impl Manager for SimpleManager {
|
||||
fn alloc_page(&mut self, pu: PageUsage) -> Result<usize, Errno> {
|
||||
self.alloc_single_index(pu)
|
||||
.map(|r| (self.base_index + r) * PAGE_SIZE)
|
||||
let res = self.alloc_single_index(pu)
|
||||
.map(|r| (self.base_index + r) * PAGE_SIZE);
|
||||
if res.is_ok() {
|
||||
self.update_stats_alloc(pu, 1);
|
||||
}
|
||||
res
|
||||
}
|
||||
fn alloc_contiguous_pages(&mut self, pu: PageUsage, count: usize) -> Result<usize, Errno> {
|
||||
'l0: for i in 0..self.pages.len() {
|
||||
@@ -75,6 +116,7 @@ unsafe impl Manager for SimpleManager {
|
||||
page.usage = pu;
|
||||
page.refcount = 1;
|
||||
}
|
||||
self.update_stats_alloc(pu, count);
|
||||
return Ok((self.base_index + i) * PAGE_SIZE);
|
||||
}
|
||||
Err(Errno::OutOfMemory)
|
||||
@@ -83,6 +125,7 @@ unsafe impl Manager for SimpleManager {
|
||||
let index = self.page_index(addr);
|
||||
let page = &mut self.pages[index];
|
||||
|
||||
let usage = page.usage;
|
||||
assert!(page.usage != PageUsage::Reserved && page.usage != PageUsage::Available);
|
||||
|
||||
if page.refcount > 1 {
|
||||
@@ -92,6 +135,10 @@ unsafe impl Manager for SimpleManager {
|
||||
page.usage = PageUsage::Available;
|
||||
page.refcount = 0;
|
||||
}
|
||||
|
||||
drop(page);
|
||||
self.update_stats_free(usage, 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -130,6 +177,10 @@ unsafe impl Manager for SimpleManager {
|
||||
}
|
||||
Ok(src)
|
||||
}
|
||||
|
||||
fn statistics(&self) -> PageStatistics {
|
||||
self.stats.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) static MANAGER: IrqSafeSpinLock<Option<SimpleManager>> = IrqSafeSpinLock::new(None);
|
||||
|
||||
@@ -32,6 +32,16 @@ pub enum PageUsage {
|
||||
Filesystem,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PageStatistics {
|
||||
available: usize,
|
||||
kernel: usize,
|
||||
kernel_heap: usize,
|
||||
paging: usize,
|
||||
user_private: usize,
|
||||
filesystem: usize,
|
||||
}
|
||||
|
||||
/// Data structure representing a single physical memory page
|
||||
pub struct PageInfo {
|
||||
refcount: usize,
|
||||
@@ -66,18 +76,57 @@ impl Iterator for SimpleMemoryIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "verbose")]
|
||||
fn trace_alloc(loc: &core::panic::Location, pu: PageUsage, base: usize, count: usize) {
|
||||
use crate::debug::Level;
|
||||
println!(
|
||||
Level::Debug,
|
||||
"\x1B[36;1m[phys/alloc] {}:{} {:?} {:#x}..{:#x}\x1B[0m",
|
||||
loc.file(),
|
||||
loc.line(),
|
||||
pu,
|
||||
base,
|
||||
base + count * PAGE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "verbose")]
|
||||
fn trace_free(loc: &core::panic::Location, page: usize) {
|
||||
use crate::debug::Level;
|
||||
println!(
|
||||
Level::Debug,
|
||||
"\x1B[36;1m[phys/free] {}:{} {:#x}..{:#x}\x1B[0m",
|
||||
loc.file(),
|
||||
loc.line(),
|
||||
page,
|
||||
page + PAGE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/// Allocates a contiguous range of `count` physical memory pages.
|
||||
#[cfg_attr(feature = "verbose", track_caller)]
|
||||
pub fn alloc_contiguous_pages(pu: PageUsage, count: usize) -> Result<usize, Errno> {
|
||||
MANAGER
|
||||
let res = MANAGER
|
||||
.lock()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.alloc_contiguous_pages(pu, count)
|
||||
.alloc_contiguous_pages(pu, count);
|
||||
#[cfg(feature = "verbose")]
|
||||
if let Ok(base) = res {
|
||||
trace_alloc(&core::panic::Location::caller(), pu, base, count);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
/// Allocates a single physical memory page.
|
||||
#[cfg_attr(feature = "verbose", track_caller)]
|
||||
pub fn alloc_page(pu: PageUsage) -> Result<usize, Errno> {
|
||||
MANAGER.lock().as_mut().unwrap().alloc_page(pu)
|
||||
let res = MANAGER.lock().as_mut().unwrap().alloc_page(pu);
|
||||
#[cfg(feature = "verbose")]
|
||||
if let Ok(base) = res {
|
||||
trace_alloc(&core::panic::Location::caller(), pu, base, 1);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
/// Releases a single physical memory page back for further allocation.
|
||||
@@ -85,10 +134,19 @@ pub fn alloc_page(pu: PageUsage) -> Result<usize, Errno> {
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: accepts arbitrary `page` arguments
|
||||
#[cfg_attr(feature = "verbose", track_caller)]
|
||||
pub unsafe fn free_page(page: usize) -> Result<(), Errno> {
|
||||
#[cfg(feature = "verbose")]
|
||||
{
|
||||
trace_free(&core::panic::Location::caller(), page);
|
||||
}
|
||||
MANAGER.lock().as_mut().unwrap().free_page(page)
|
||||
}
|
||||
|
||||
pub fn statistics() -> PageStatistics {
|
||||
MANAGER.lock().as_ref().unwrap().statistics()
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: accepts arbitrary `page` arguments
|
||||
|
||||
Reference in New Issue
Block a user