feature: statistics for phys mem module

This commit is contained in:
2021-11-11 14:40:08 +02:00
parent afc6ccc8dd
commit 67ab37865e
4 changed files with 126 additions and 6 deletions
+3
View File
@@ -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
+8
View File
@@ -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';
}
+54 -3
View File
@@ -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);
+61 -3
View File
@@ -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