xref: /DragonOS/kernel/src/mm/allocator/bump.rs (revision 45626c859f95054b76d8b59afcbd24c6b235026f)
140fe15e0SLoGin /// @Auther: Kong
240fe15e0SLoGin /// @Date: 2023-03-27 06:54:08
340fe15e0SLoGin /// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
440fe15e0SLoGin /// @Description: bump allocator线性分配器
540fe15e0SLoGin use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
6*45626c85SLoGin use crate::mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr, PhysMemoryArea};
740fe15e0SLoGin use core::marker::PhantomData;
840fe15e0SLoGin 
940fe15e0SLoGin /// 线性分配器
1040fe15e0SLoGin pub struct BumpAllocator<MMA> {
1140fe15e0SLoGin     // 表示当前分配的物理内存的偏移量.
1240fe15e0SLoGin     offset: usize,
1340fe15e0SLoGin     // 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。
1440fe15e0SLoGin     phantom: PhantomData<MMA>,
1540fe15e0SLoGin }
1640fe15e0SLoGin 
1740fe15e0SLoGin /// 为BumpAllocator实现FrameAllocator
1840fe15e0SLoGin impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
1940fe15e0SLoGin     /// @brief: 创建一个线性分配器
2040fe15e0SLoGin     /// @param Fareas 当前的内存区域
2140fe15e0SLoGin     /// @param offset 当前的偏移量
2240fe15e0SLoGin     /// @return 分配器本身
23*45626c85SLoGin     pub fn new(offset: usize) -> Self {
2440fe15e0SLoGin         Self {
2540fe15e0SLoGin             offset,
2640fe15e0SLoGin             phantom: PhantomData,
2740fe15e0SLoGin         }
2840fe15e0SLoGin     }
29*45626c85SLoGin 
3040fe15e0SLoGin     // @brief 获取当前分配的物理内存的偏移量
3140fe15e0SLoGin     pub fn offset(&self) -> usize {
3240fe15e0SLoGin         return self.offset;
3340fe15e0SLoGin     }
3499dbf38dSLoGin 
3599dbf38dSLoGin     /// 返回剩余的尚未被分配的物理内存区域
3699dbf38dSLoGin     ///
3799dbf38dSLoGin     /// ## 返回值
3899dbf38dSLoGin     ///
3999dbf38dSLoGin     /// - `result_area`:剩余的尚未被分配的物理内存区域的数组
4099dbf38dSLoGin     /// - `offset_aligned`:返回的第一个物理内存区域内,已经分配的偏移量(相对于物理内存区域的已对齐的起始地址)
4199dbf38dSLoGin     pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> {
4299dbf38dSLoGin         let mut offset = self.offset();
4399dbf38dSLoGin 
4499dbf38dSLoGin         let mut ret_offset_aligned = 0;
4599dbf38dSLoGin 
4699dbf38dSLoGin         let mut res_cnt = 0;
4799dbf38dSLoGin 
48*45626c85SLoGin         let total_num = mem_block_manager().total_initial_memory_regions();
4999dbf38dSLoGin         // 遍历所有的物理内存区域
50*45626c85SLoGin         for i in 0..total_num {
51*45626c85SLoGin             let area = mem_block_manager().get_initial_memory_region(i).unwrap();
5299dbf38dSLoGin             // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
5399dbf38dSLoGin             // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
5499dbf38dSLoGin             let area_base = area.area_base_aligned().data();
5599dbf38dSLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
5699dbf38dSLoGin             // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
5799dbf38dSLoGin             let area_end = area.area_end_aligned().data();
5899dbf38dSLoGin 
5999dbf38dSLoGin             // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
6099dbf38dSLoGin             if offset >= area_end {
6199dbf38dSLoGin                 continue;
6299dbf38dSLoGin             }
6399dbf38dSLoGin 
6499dbf38dSLoGin             // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
6599dbf38dSLoGin             if offset < area_base {
6699dbf38dSLoGin                 offset = area_base;
6799dbf38dSLoGin             } else if offset < area_end {
6899dbf38dSLoGin                 // 将offset对齐到PAGE_SIZE
6999dbf38dSLoGin                 offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
7099dbf38dSLoGin             }
7199dbf38dSLoGin             // found
7299dbf38dSLoGin             if offset + 1 * MMA::PAGE_SIZE <= area_end {
73*45626c85SLoGin                 for j in i..total_num {
74*45626c85SLoGin                     let aj = mem_block_manager().get_initial_memory_region(j).unwrap();
75*45626c85SLoGin                     if aj.area_base_aligned() < aj.area_end_aligned() {
76*45626c85SLoGin                         result_area[res_cnt] = aj;
7799dbf38dSLoGin                         res_cnt += 1;
7899dbf38dSLoGin                     }
7999dbf38dSLoGin                 }
8099dbf38dSLoGin                 ret_offset_aligned = offset;
8199dbf38dSLoGin                 break;
8299dbf38dSLoGin             }
8399dbf38dSLoGin         }
8499dbf38dSLoGin 
8599dbf38dSLoGin         let res_cnt = unsafe { Self::arch_remain_areas(result_area, res_cnt) };
8699dbf38dSLoGin         if res_cnt == 0 {
8799dbf38dSLoGin             return None;
8899dbf38dSLoGin         } else {
8999dbf38dSLoGin             return Some(ret_offset_aligned);
9099dbf38dSLoGin         }
9199dbf38dSLoGin     }
9240fe15e0SLoGin }
9340fe15e0SLoGin 
9440fe15e0SLoGin impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
9540fe15e0SLoGin     /// @brief: 分配count个物理页帧
9640fe15e0SLoGin     /// @param  mut self
9740fe15e0SLoGin     /// @param  count 分配的页帧数量
9840fe15e0SLoGin     /// @return 分配后的物理地址
9940fe15e0SLoGin     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
10040fe15e0SLoGin         let mut offset = self.offset();
101*45626c85SLoGin 
102*45626c85SLoGin         let iter = mem_block_manager().to_iter();
103*45626c85SLoGin 
10440fe15e0SLoGin         // 遍历所有的物理内存区域
105*45626c85SLoGin         for area in iter {
10640fe15e0SLoGin             // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
10740fe15e0SLoGin             // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
10899dbf38dSLoGin             let area_base = area.area_base_aligned().data();
10940fe15e0SLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
11040fe15e0SLoGin             // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
11199dbf38dSLoGin             let area_end = area.area_end_aligned().data();
11240fe15e0SLoGin 
11340fe15e0SLoGin             // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
11440fe15e0SLoGin             if offset >= area_end {
11540fe15e0SLoGin                 continue;
11640fe15e0SLoGin             }
11740fe15e0SLoGin 
11840fe15e0SLoGin             // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
11940fe15e0SLoGin             if offset < area_base {
12040fe15e0SLoGin                 offset = area_base;
12140fe15e0SLoGin             } else if offset < area_end {
12240fe15e0SLoGin                 // 将offset对齐到PAGE_SIZE
12340fe15e0SLoGin                 offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
12440fe15e0SLoGin             }
12540fe15e0SLoGin             // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧
12640fe15e0SLoGin             if offset + count.data() * MMA::PAGE_SIZE <= area_end {
12740fe15e0SLoGin                 let res_page_phys = offset;
12840fe15e0SLoGin                 // 将offset增加至分配后的内存
12940fe15e0SLoGin                 self.offset = offset + count.data() * MMA::PAGE_SIZE;
13040fe15e0SLoGin 
13140fe15e0SLoGin                 return Some((PhysAddr(res_page_phys), count));
13240fe15e0SLoGin             }
13340fe15e0SLoGin         }
13440fe15e0SLoGin         return None;
13540fe15e0SLoGin     }
13640fe15e0SLoGin 
13740fe15e0SLoGin     unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) {
13840fe15e0SLoGin         // TODO: 支持释放页帧
13940fe15e0SLoGin         unimplemented!("BumpAllocator::free not implemented");
14040fe15e0SLoGin     }
14140fe15e0SLoGin     /// @brief: 获取内存区域页帧的使用情况
14240fe15e0SLoGin     /// @param  self
14340fe15e0SLoGin     /// @return 页帧的使用情况
14440fe15e0SLoGin     unsafe fn usage(&self) -> PageFrameUsage {
14540fe15e0SLoGin         let mut total = 0;
14640fe15e0SLoGin         let mut used = 0;
147*45626c85SLoGin         let iter = mem_block_manager().to_iter();
148*45626c85SLoGin         for area in iter {
14940fe15e0SLoGin             // 将area的base地址与PAGE_SIZE对齐,对其时向上取整
15040fe15e0SLoGin             let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
15140fe15e0SLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整
15240fe15e0SLoGin             let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
15340fe15e0SLoGin 
15440fe15e0SLoGin             total += (area_end - area_base) >> MMA::PAGE_SHIFT;
15540fe15e0SLoGin             // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中
15640fe15e0SLoGin             if self.offset >= area_end {
15740fe15e0SLoGin                 used += (area_end - area_base) >> MMA::PAGE_SHIFT;
15840fe15e0SLoGin             } else if self.offset < area_base {
15940fe15e0SLoGin                 // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中
16040fe15e0SLoGin                 continue;
16140fe15e0SLoGin             } else {
16240fe15e0SLoGin                 used += (self.offset - area_base) >> MMA::PAGE_SHIFT;
16340fe15e0SLoGin             }
16440fe15e0SLoGin         }
16540fe15e0SLoGin         let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total));
16640fe15e0SLoGin         return frame;
16740fe15e0SLoGin     }
16840fe15e0SLoGin }
169