Browse Source

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

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

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin 3 days ago
parent
commit
6ac8e1f0cd
2 changed files with 29 additions and 38 deletions
  1. 3 0
      kernel/src/mm/memblock.rs
  2. 26 38
      kernel/src/mm/mmio_buddy.rs

+ 3 - 0
kernel/src/mm/memblock.rs

@@ -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 {

+ 26 - 38
kernel/src/mm/mmio_buddy.rs

@@ -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();
     }
 }