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