Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mm): add slab usage calculation #768

Merged
merged 11 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 71 additions & 6 deletions kernel/crates/rust-slabmalloc/src/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! The ZoneAllocator achieves this by having many `SCAllocator`

use crate::*;
use core::sync::atomic::Ordering;

/// Creates an instance of a zone, we do this in a macro because we
/// re-use the code in const and non-const functions
Expand All @@ -24,6 +25,7 @@ macro_rules! new_zone {
SCAllocator::new(1 << 10), // 1024
SCAllocator::new(1 << 11), // 2048 ],
],
total: 0,
}
};
}
Expand All @@ -38,6 +40,7 @@ macro_rules! new_zone {
/// to provide the underlying `SCAllocator` with more memory in case it runs out.
pub struct ZoneAllocator<'a> {
small_slabs: [SCAllocator<'a, ObjectPage<'a>>; ZoneAllocator::MAX_BASE_SIZE_CLASSES],
total: u64,
}

impl<'a> Default for ZoneAllocator<'a> {
Expand All @@ -52,17 +55,13 @@ enum Slab {
}

impl<'a> ZoneAllocator<'a> {
/// Maximum size that allocated within LargeObjectPages (2 MiB).
/// This is also the maximum object size that this allocator can handle.
pub const MAX_ALLOC_SIZE: usize = 1 << 11;

/// Maximum size which is allocated with ObjectPages (4 KiB pages).
///
/// e.g. this is 4 KiB - 80 bytes of meta-data.
pub const MAX_BASE_ALLOC_SIZE: usize = 256;
pub const MAX_BASE_ALLOC_SIZE: usize = 1 << 11;

/// How many allocators of type SCAllocator<ObjectPage> we have.
const MAX_BASE_SIZE_CLASSES: usize = 9;
pub const MAX_BASE_SIZE_CLASSES: usize = 9;

#[cfg(feature = "unstable")]
pub const fn new() -> ZoneAllocator<'a> {
Expand Down Expand Up @@ -126,6 +125,43 @@ impl<'a> ZoneAllocator<'a> {
}
}
}

/// 获取scallocator中的还未被分配的空间
pub fn free_space(&mut self) -> u64 {
// 记录空闲空间
let mut free = 0;
// scallocator的数量
let mut count = 0;

// 遍历所有scallocator
while count < ZoneAllocator::MAX_BASE_SIZE_CLASSES {
// 获取scallocator
let scallocator = &mut self.small_slabs[count];
// 遍历scallocator中的部分分配的page(partial_page)
for slab_page in scallocator.slabs.iter_mut() {
// 每个page的obj_per_page,即每个page的最大object数,这里用来赋值给obj_count
// 用来统计page中还可以分配多少个object
let mut obj_count = scallocator.obj_per_page;
// 遍历page中的bitfield(用来统计内存分配情况的u64数组)
for (_base_idx, b) in slab_page.bitfield().iter().enumerate() {
let bitval = b.load(Ordering::Relaxed);
let negated = !bitval;
let allocated_count = negated.trailing_zeros() as usize;
// 减去已分配的object数
obj_count -= allocated_count;
}
// 剩余可分配object数乘上page中规定的每个object的大小,即空闲空间
free += obj_count * scallocator.size();
}
count -= 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个测试过吗?count -= 1;怎么能跑的。

}
free as u64
}

pub fn usage(&mut self) -> SlabUsage {
let free_num = self.free_space();
SlabUsage::new(self.total, free_num)
}
}

unsafe impl<'a> crate::Allocator<'a> for ZoneAllocator<'a> {
Expand Down Expand Up @@ -162,9 +198,38 @@ unsafe impl<'a> crate::Allocator<'a> for ZoneAllocator<'a> {
match ZoneAllocator::get_slab(layout.size()) {
Slab::Base(idx) => {
self.small_slabs[idx].refill(new_page);
// 每refill一个page就为slab的总空间统计加上4KB
self.total += 4096;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个不要直接写4096,而是应该用OBJECT_PAGE_SIZEE。

Ok(())
}
Slab::Unsupported => Err(AllocationError::InvalidLayout),
}
}
}

/// Slab内存空间使用情况
pub struct SlabUsage {
// slab总共使用的内存空间
total: u64,
// slab的空闲空间
free: u64,
}

impl SlabUsage {
/// 初始化SlabUsage
pub fn new(total: u64, free: u64) -> Self {
Self { total, free }
}

pub fn total(&self) -> u64 {
self.total
}

pub fn used(&self) -> u64 {
self.total - self.free
}

pub fn free(&self) -> u64 {
self.free
}
}
10 changes: 9 additions & 1 deletion kernel/src/mm/allocator/slab.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! 当前slab分配器暂时不使用,等待后续完善后合并主线
#![allow(dead_code)]

use core::{alloc::Layout, ptr::NonNull, sync::atomic::AtomicBool};
use core::{alloc::Layout, panic, ptr::NonNull, sync::atomic::AtomicBool};

use alloc::boxed::Box;
use slabmalloc::*;
Expand Down Expand Up @@ -74,3 +74,11 @@ pub unsafe fn slab_init() {
pub fn slab_init_state() -> bool {
unsafe { *SLABINITSTATE.get_mut() }
}

pub unsafe fn slab_usage() -> SlabUsage {
if let Some(ref mut slab) = SLABALLOCATOR {
slab.zone.usage()
} else {
SlabUsage::new(0, 0)
}
}
5 changes: 3 additions & 2 deletions kernel/src/syscall/misc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
arch::{mm::LockedFrameAllocator, rand::rand},
libs::rand::GRandFlags,
mm::allocator::page_frame::FrameAllocator,
mm::allocator::{page_frame::FrameAllocator, slab::slab_usage},
};
use alloc::vec::Vec;
use core::cmp;
Expand Down Expand Up @@ -38,10 +38,11 @@ impl Syscall {
let mut sysinfo = SysInfo::default();

let mem = unsafe { LockedFrameAllocator.usage() };
let slab_usage = unsafe { slab_usage() };
sysinfo.uptime = 0;
sysinfo.loads = [0; 3];
sysinfo.totalram = mem.total().bytes() as u64;
sysinfo.freeram = mem.free().bytes() as u64;
sysinfo.freeram = mem.free().bytes() as u64 + slab_usage.free();
sysinfo.sharedram = 0;
sysinfo.bufferram = 0;
sysinfo.totalswap = 0;
Expand Down
2 changes: 2 additions & 0 deletions user/apps/test-backlog/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ test-release:
.PHONY: install
install:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

$(warning test envs $(DADK_CURRENT_BUILD_DIR))
Loading