mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 10:15:03 +00:00
refactor(mm): 优化内存管理模块代码结构 (#1181)
- 将 `MmioBuddyMemPool` 中的 `free_regions` 从数组改为 `Vec`, 降低初始化的栈内存使用 - 移除不必要的 `LinkedList` 依赖,使用 `Vec` 替代 Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
parent
1032474cbf
commit
6ac8e1f0cd
@ -40,6 +40,9 @@ impl MemBlockManager {
|
|||||||
pub const MIN_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(0);
|
pub const MIN_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(0);
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const MAX_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(usize::MAX);
|
pub const MAX_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(usize::MAX);
|
||||||
|
|
||||||
|
/// 由于这个函数只在全局调用,因此不需要担心栈上溢出问题
|
||||||
|
#[allow(clippy::large_stack_frames)]
|
||||||
const fn new() -> Self {
|
const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: SpinLock::new(InnerMemBlockManager {
|
inner: SpinLock::new(InnerMemBlockManager {
|
||||||
|
@ -5,9 +5,7 @@ use crate::mm::page::{PAGE_1G_SHIFT, PAGE_4K_SHIFT};
|
|||||||
use crate::mm::{MMArch, MemoryManagementArch};
|
use crate::mm::{MMArch, MemoryManagementArch};
|
||||||
use crate::process::ProcessManager;
|
use crate::process::ProcessManager;
|
||||||
|
|
||||||
use alloc::{collections::LinkedList, vec::Vec};
|
use alloc::vec::Vec;
|
||||||
use core::mem;
|
|
||||||
use core::mem::MaybeUninit;
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
@ -43,25 +41,18 @@ pub enum MmioResult {
|
|||||||
pub struct MmioBuddyMemPool {
|
pub struct MmioBuddyMemPool {
|
||||||
pool_start_addr: VirtAddr,
|
pool_start_addr: VirtAddr,
|
||||||
pool_size: usize,
|
pool_size: usize,
|
||||||
free_regions: [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize],
|
free_regions: Vec<SpinLock<MmioFreeRegionList>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MmioBuddyMemPool {
|
impl MmioBuddyMemPool {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
|
let mut free_regions: Vec<SpinLock<MmioFreeRegionList>> =
|
||||||
MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };
|
Vec::with_capacity(MMIO_BUDDY_REGION_COUNT as usize);
|
||||||
for i in 0..MMIO_BUDDY_REGION_COUNT {
|
|
||||||
free_regions[i as usize] = MaybeUninit::new(SpinLock::new(MmioFreeRegionList::new()));
|
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 {
|
let pool = MmioBuddyMemPool {
|
||||||
pool_start_addr: MMArch::MMIO_BASE,
|
pool_start_addr: MMArch::MMIO_BASE,
|
||||||
@ -70,7 +61,6 @@ impl MmioBuddyMemPool {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert!(pool.pool_start_addr.data() % PAGE_1G_SIZE == 0);
|
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 vaddr_base = MMArch::MMIO_BASE;
|
||||||
let mut remain_size = MMArch::MMIO_SIZE;
|
let mut remain_size = MMArch::MMIO_SIZE;
|
||||||
@ -122,6 +112,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Ok(i32) 返回0
|
/// @return Ok(i32) 返回0
|
||||||
///
|
///
|
||||||
/// @return Err(SystemError) 返回错误码
|
/// @return Err(SystemError) 返回错误码
|
||||||
|
#[inline(never)]
|
||||||
fn give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError> {
|
fn give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError> {
|
||||||
// 确保内存对齐,低位都要为0
|
// 确保内存对齐,低位都要为0
|
||||||
if (vaddr.data() & ((1 << exp) - 1)) != 0 {
|
if (vaddr.data() & ((1 << exp) - 1)) != 0 {
|
||||||
@ -178,13 +169,13 @@ impl MmioBuddyMemPool {
|
|||||||
}
|
}
|
||||||
// 没有恰好符合要求的内存块
|
// 没有恰好符合要求的内存块
|
||||||
// 注意:exp对应的链表list_guard已上锁【注意避免死锁问题】
|
// 注意:exp对应的链表list_guard已上锁【注意避免死锁问题】
|
||||||
if list_guard.num_free == 0 {
|
if list_guard.free_count() == 0 {
|
||||||
// 找到最小符合申请范围的内存块
|
// 找到最小符合申请范围的内存块
|
||||||
// 将大的内存块依次分成小块内存,直到能够满足exp大小,即将exp+1分成两块exp
|
// 将大的内存块依次分成小块内存,直到能够满足exp大小,即将exp+1分成两块exp
|
||||||
for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 {
|
for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 {
|
||||||
let pop_list: &mut SpinLockGuard<MmioFreeRegionList> =
|
let pop_list: &mut SpinLockGuard<MmioFreeRegionList> =
|
||||||
&mut self.free_regions[exp2index(e)].lock();
|
&mut self.free_regions[exp2index(e)].lock();
|
||||||
if pop_list.num_free == 0 {
|
if pop_list.free_count() == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +223,7 @@ impl MmioBuddyMemPool {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// 判断是否获得了exp大小的内存块
|
// 判断是否获得了exp大小的内存块
|
||||||
if list_guard.num_free > 0 {
|
if list_guard.free_count() > 0 {
|
||||||
match self.pop_block(list_guard) {
|
match self.pop_block(list_guard) {
|
||||||
Ok(ret) => return Ok(ret),
|
Ok(ret) => return Ok(ret),
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -283,7 +274,7 @@ impl MmioBuddyMemPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//判断是否获得了exp大小的内存块
|
//判断是否获得了exp大小的内存块
|
||||||
if list_guard.num_free > 0 {
|
if list_guard.free_count() > 0 {
|
||||||
match self.pop_block(list_guard) {
|
match self.pop_block(list_guard) {
|
||||||
Ok(ret) => return Ok(ret),
|
Ok(ret) => return Ok(ret),
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -325,8 +316,7 @@ impl MmioBuddyMemPool {
|
|||||||
region: MmioBuddyAddrRegion,
|
region: MmioBuddyAddrRegion,
|
||||||
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) {
|
) {
|
||||||
list_guard.list.push_back(region);
|
list_guard.list.push(region);
|
||||||
list_guard.num_free += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
|
/// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
|
||||||
@ -365,7 +355,6 @@ impl MmioBuddyMemPool {
|
|||||||
.extract_if(|x| x.vaddr == buddy_vaddr)
|
.extract_if(|x| x.vaddr == buddy_vaddr)
|
||||||
.collect();
|
.collect();
|
||||||
if element.len() == 1 {
|
if element.len() == 1 {
|
||||||
list_guard.num_free -= 1;
|
|
||||||
return Ok(element.pop().unwrap());
|
return Ok(element.pop().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,8 +375,7 @@ impl MmioBuddyMemPool {
|
|||||||
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) -> Result<MmioBuddyAddrRegion, MmioResult> {
|
) -> Result<MmioBuddyAddrRegion, MmioResult> {
|
||||||
if !list_guard.list.is_empty() {
|
if !list_guard.list.is_empty() {
|
||||||
list_guard.num_free -= 1;
|
return Ok(list_guard.list.pop().unwrap());
|
||||||
return Ok(list_guard.list.pop_back().unwrap());
|
|
||||||
}
|
}
|
||||||
return Err(MmioResult::ISEMPTY);
|
return Err(MmioResult::ISEMPTY);
|
||||||
}
|
}
|
||||||
@ -412,22 +400,22 @@ impl MmioBuddyMemPool {
|
|||||||
high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) -> Result<MmioResult, MmioResult> {
|
) -> Result<MmioResult, MmioResult> {
|
||||||
// 至少要两个内存块才能合并
|
// 至少要两个内存块才能合并
|
||||||
if list_guard.num_free <= 1 {
|
if list_guard.free_count() <= 1 {
|
||||||
return Err(MmioResult::EINVAL);
|
return Err(MmioResult::EINVAL);
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
if list_guard.num_free <= 1 {
|
if list_guard.free_count() <= 1 {
|
||||||
break;
|
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) {
|
match self.pop_buddy_block(vaddr, exp, list_guard) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Ok(buddy_region) => {
|
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();
|
let copy_region = region.clone();
|
||||||
// 在两块内存都被取出之后才进行合并
|
// 在两块内存都被取出之后才进行合并
|
||||||
match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
|
match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
|
||||||
@ -593,17 +581,17 @@ impl MmioBuddyAddrRegion {
|
|||||||
/// @brief 空闲页数组结构体
|
/// @brief 空闲页数组结构体
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct MmioFreeRegionList {
|
pub struct MmioFreeRegionList {
|
||||||
/// 存储mmio_buddy的地址链表
|
/// 存储mmio_buddy的地址数组
|
||||||
list: LinkedList<MmioBuddyAddrRegion>,
|
list: Vec<MmioBuddyAddrRegion>,
|
||||||
/// 空闲块的数量
|
|
||||||
num_free: i64,
|
|
||||||
}
|
}
|
||||||
impl MmioFreeRegionList {
|
impl MmioFreeRegionList {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn new() -> Self {
|
const fn new() -> Self {
|
||||||
return MmioFreeRegionList {
|
Self { list: Vec::new() }
|
||||||
..Default::default()
|
}
|
||||||
};
|
|
||||||
|
fn free_count(&self) -> usize {
|
||||||
|
return self.list.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user