refactor(mm): 优化内存管理模块代码结构 (#1181)

- 将 `MmioBuddyMemPool` 中的 `free_regions` 从数组改为 `Vec`, 降低初始化的栈内存使用
- 移除不必要的 `LinkedList` 依赖,使用 `Vec` 替代

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin 2025-05-29 17:40:11 +08:00 committed by GitHub
parent 1032474cbf
commit 6ac8e1f0cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 38 deletions

View File

@ -40,6 +40,9 @@ impl MemBlockManager {
pub const MIN_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(0);
#[allow(dead_code)]
pub const MAX_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(usize::MAX);
/// 由于这个函数只在全局调用,因此不需要担心栈上溢出问题
#[allow(clippy::large_stack_frames)]
const fn new() -> Self {
Self {
inner: SpinLock::new(InnerMemBlockManager {

View File

@ -5,9 +5,7 @@ use crate::mm::page::{PAGE_1G_SHIFT, PAGE_4K_SHIFT};
use crate::mm::{MMArch, MemoryManagementArch};
use crate::process::ProcessManager;
use alloc::{collections::LinkedList, vec::Vec};
use core::mem;
use core::mem::MaybeUninit;
use alloc::vec::Vec;
use core::sync::atomic::{AtomicBool, Ordering};
use log::{debug, error, info, warn};
use system_error::SystemError;
@ -43,25 +41,18 @@ pub enum MmioResult {
pub struct MmioBuddyMemPool {
pool_start_addr: VirtAddr,
pool_size: usize,
free_regions: [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize],
free_regions: Vec<SpinLock<MmioFreeRegionList>>,
}
impl MmioBuddyMemPool {
#[inline(never)]
fn new() -> Self {
let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };
for i in 0..MMIO_BUDDY_REGION_COUNT {
free_regions[i as usize] = MaybeUninit::new(SpinLock::new(MmioFreeRegionList::new()));
let mut free_regions: Vec<SpinLock<MmioFreeRegionList>> =
Vec::with_capacity(MMIO_BUDDY_REGION_COUNT as usize);
for _ in 0..MMIO_BUDDY_REGION_COUNT {
free_regions.push(SpinLock::new(MmioFreeRegionList::new()));
}
let free_regions = unsafe {
mem::transmute::<
[core::mem::MaybeUninit<
crate::libs::spinlock::SpinLock<crate::mm::mmio_buddy::MmioFreeRegionList>,
>; MMIO_BUDDY_REGION_COUNT as usize],
[SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize],
>(free_regions)
};
let pool = MmioBuddyMemPool {
pool_start_addr: MMArch::MMIO_BASE,
@ -70,7 +61,6 @@ impl MmioBuddyMemPool {
};
assert!(pool.pool_start_addr.data() % PAGE_1G_SIZE == 0);
debug!("MMIO buddy pool init: created");
let mut vaddr_base = MMArch::MMIO_BASE;
let mut remain_size = MMArch::MMIO_SIZE;
@ -122,6 +112,7 @@ impl MmioBuddyMemPool {
/// @return Ok(i32) 返回0
///
/// @return Err(SystemError) 返回错误码
#[inline(never)]
fn give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError> {
// 确保内存对齐低位都要为0
if (vaddr.data() & ((1 << exp) - 1)) != 0 {
@ -178,13 +169,13 @@ impl MmioBuddyMemPool {
}
// 没有恰好符合要求的内存块
// 注意exp对应的链表list_guard已上锁【注意避免死锁问题】
if list_guard.num_free == 0 {
if list_guard.free_count() == 0 {
// 找到最小符合申请范围的内存块
// 将大的内存块依次分成小块内存直到能够满足exp大小即将exp+1分成两块exp
for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 {
let pop_list: &mut SpinLockGuard<MmioFreeRegionList> =
&mut self.free_regions[exp2index(e)].lock();
if pop_list.num_free == 0 {
if pop_list.free_count() == 0 {
continue;
}
@ -232,7 +223,7 @@ impl MmioBuddyMemPool {
break;
}
// 判断是否获得了exp大小的内存块
if list_guard.num_free > 0 {
if list_guard.free_count() > 0 {
match self.pop_block(list_guard) {
Ok(ret) => return Ok(ret),
Err(err) => return Err(err),
@ -283,7 +274,7 @@ impl MmioBuddyMemPool {
}
//判断是否获得了exp大小的内存块
if list_guard.num_free > 0 {
if list_guard.free_count() > 0 {
match self.pop_block(list_guard) {
Ok(ret) => return Ok(ret),
Err(err) => return Err(err),
@ -325,8 +316,7 @@ impl MmioBuddyMemPool {
region: MmioBuddyAddrRegion,
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) {
list_guard.list.push_back(region);
list_guard.num_free += 1;
list_guard.list.push(region);
}
/// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
@ -365,7 +355,6 @@ impl MmioBuddyMemPool {
.extract_if(|x| x.vaddr == buddy_vaddr)
.collect();
if element.len() == 1 {
list_guard.num_free -= 1;
return Ok(element.pop().unwrap());
}
@ -386,8 +375,7 @@ impl MmioBuddyMemPool {
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) -> Result<MmioBuddyAddrRegion, MmioResult> {
if !list_guard.list.is_empty() {
list_guard.num_free -= 1;
return Ok(list_guard.list.pop_back().unwrap());
return Ok(list_guard.list.pop().unwrap());
}
return Err(MmioResult::ISEMPTY);
}
@ -412,22 +400,22 @@ impl MmioBuddyMemPool {
high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) -> Result<MmioResult, MmioResult> {
// 至少要两个内存块才能合并
if list_guard.num_free <= 1 {
if list_guard.free_count() <= 1 {
return Err(MmioResult::EINVAL);
}
loop {
if list_guard.num_free <= 1 {
if list_guard.free_count() <= 1 {
break;
}
// 获取内存块
let vaddr: VirtAddr = list_guard.list.back().unwrap().vaddr;
let vaddr: VirtAddr = list_guard.list.last().unwrap().vaddr;
// 获取伙伴内存块
match self.pop_buddy_block(vaddr, exp, list_guard) {
Err(err) => {
return Err(err);
}
Ok(buddy_region) => {
let region: MmioBuddyAddrRegion = list_guard.list.pop_back().unwrap();
let region: MmioBuddyAddrRegion = list_guard.list.pop().unwrap();
let copy_region = region.clone();
// 在两块内存都被取出之后才进行合并
match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
@ -593,17 +581,17 @@ impl MmioBuddyAddrRegion {
/// @brief 空闲页数组结构体
#[derive(Debug, Default)]
pub struct MmioFreeRegionList {
/// 存储mmio_buddy的地址链表
list: LinkedList<MmioBuddyAddrRegion>,
/// 空闲块的数量
num_free: i64,
/// 存储mmio_buddy的地址数组
list: Vec<MmioBuddyAddrRegion>,
}
impl MmioFreeRegionList {
#[allow(dead_code)]
fn new() -> Self {
return MmioFreeRegionList {
..Default::default()
};
const fn new() -> Self {
Self { list: Vec::new() }
}
fn free_count(&self) -> usize {
return self.list.len();
}
}