1*40fe15e0SLoGin /// @Auther: Kong 2*40fe15e0SLoGin /// @Date: 2023-03-27 06:54:08 3*40fe15e0SLoGin /// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs 4*40fe15e0SLoGin /// @Description: bump allocator线性分配器 5*40fe15e0SLoGin use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; 6*40fe15e0SLoGin use crate::mm::{MemoryManagementArch, PhysAddr, PhysMemoryArea}; 7*40fe15e0SLoGin use core::marker::PhantomData; 8*40fe15e0SLoGin 9*40fe15e0SLoGin /// 线性分配器 10*40fe15e0SLoGin pub struct BumpAllocator<MMA> { 11*40fe15e0SLoGin // 表示可用物理内存区域的数组。每个 PhysMemoryArea 结构体描述一个物理内存区域的起始地址和大小。 12*40fe15e0SLoGin areas: &'static [PhysMemoryArea], 13*40fe15e0SLoGin // 表示当前分配的物理内存的偏移量. 14*40fe15e0SLoGin offset: usize, 15*40fe15e0SLoGin // 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。 16*40fe15e0SLoGin phantom: PhantomData<MMA>, 17*40fe15e0SLoGin } 18*40fe15e0SLoGin 19*40fe15e0SLoGin /// 为BumpAllocator实现FrameAllocator 20*40fe15e0SLoGin impl<MMA: MemoryManagementArch> BumpAllocator<MMA> { 21*40fe15e0SLoGin /// @brief: 创建一个线性分配器 22*40fe15e0SLoGin /// @param Fareas 当前的内存区域 23*40fe15e0SLoGin /// @param offset 当前的偏移量 24*40fe15e0SLoGin /// @return 分配器本身 25*40fe15e0SLoGin pub fn new(areas: &'static [PhysMemoryArea], offset: usize) -> Self { 26*40fe15e0SLoGin Self { 27*40fe15e0SLoGin areas, 28*40fe15e0SLoGin offset, 29*40fe15e0SLoGin phantom: PhantomData, 30*40fe15e0SLoGin } 31*40fe15e0SLoGin } 32*40fe15e0SLoGin // @brief 获取页帧使用情况 33*40fe15e0SLoGin pub fn areas(&self) -> &'static [PhysMemoryArea] { 34*40fe15e0SLoGin return self.areas; 35*40fe15e0SLoGin } 36*40fe15e0SLoGin // @brief 获取当前分配的物理内存的偏移量 37*40fe15e0SLoGin pub fn offset(&self) -> usize { 38*40fe15e0SLoGin return self.offset; 39*40fe15e0SLoGin } 40*40fe15e0SLoGin } 41*40fe15e0SLoGin 42*40fe15e0SLoGin impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> { 43*40fe15e0SLoGin /// @brief: 分配count个物理页帧 44*40fe15e0SLoGin /// @param mut self 45*40fe15e0SLoGin /// @param count 分配的页帧数量 46*40fe15e0SLoGin /// @return 分配后的物理地址 47*40fe15e0SLoGin unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 48*40fe15e0SLoGin let mut offset = self.offset(); 49*40fe15e0SLoGin // 遍历所有的物理内存区域 50*40fe15e0SLoGin for area in self.areas().iter() { 51*40fe15e0SLoGin // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整 52*40fe15e0SLoGin // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 53*40fe15e0SLoGin let area_base = (area.base.data() + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); 54*40fe15e0SLoGin // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整 55*40fe15e0SLoGin // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 56*40fe15e0SLoGin let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SIZE - 1); 57*40fe15e0SLoGin 58*40fe15e0SLoGin // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域 59*40fe15e0SLoGin if offset >= area_end { 60*40fe15e0SLoGin continue; 61*40fe15e0SLoGin } 62*40fe15e0SLoGin 63*40fe15e0SLoGin // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base 64*40fe15e0SLoGin if offset < area_base { 65*40fe15e0SLoGin offset = area_base; 66*40fe15e0SLoGin } else if offset < area_end { 67*40fe15e0SLoGin // 将offset对齐到PAGE_SIZE 68*40fe15e0SLoGin offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); 69*40fe15e0SLoGin } 70*40fe15e0SLoGin // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧 71*40fe15e0SLoGin if offset + count.data() * MMA::PAGE_SIZE <= area_end { 72*40fe15e0SLoGin let res_page_phys = offset; 73*40fe15e0SLoGin // 将offset增加至分配后的内存 74*40fe15e0SLoGin self.offset = offset + count.data() * MMA::PAGE_SIZE; 75*40fe15e0SLoGin 76*40fe15e0SLoGin return Some((PhysAddr(res_page_phys), count)); 77*40fe15e0SLoGin } 78*40fe15e0SLoGin } 79*40fe15e0SLoGin return None; 80*40fe15e0SLoGin } 81*40fe15e0SLoGin 82*40fe15e0SLoGin unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) { 83*40fe15e0SLoGin // TODO: 支持释放页帧 84*40fe15e0SLoGin unimplemented!("BumpAllocator::free not implemented"); 85*40fe15e0SLoGin } 86*40fe15e0SLoGin /// @brief: 获取内存区域页帧的使用情况 87*40fe15e0SLoGin /// @param self 88*40fe15e0SLoGin /// @return 页帧的使用情况 89*40fe15e0SLoGin unsafe fn usage(&self) -> PageFrameUsage { 90*40fe15e0SLoGin let mut total = 0; 91*40fe15e0SLoGin let mut used = 0; 92*40fe15e0SLoGin for area in self.areas().iter() { 93*40fe15e0SLoGin // 将area的base地址与PAGE_SIZE对齐,对其时向上取整 94*40fe15e0SLoGin let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 95*40fe15e0SLoGin // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整 96*40fe15e0SLoGin let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 97*40fe15e0SLoGin 98*40fe15e0SLoGin total += (area_end - area_base) >> MMA::PAGE_SHIFT; 99*40fe15e0SLoGin // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中 100*40fe15e0SLoGin if self.offset >= area_end { 101*40fe15e0SLoGin used += (area_end - area_base) >> MMA::PAGE_SHIFT; 102*40fe15e0SLoGin } else if self.offset < area_base { 103*40fe15e0SLoGin // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中 104*40fe15e0SLoGin continue; 105*40fe15e0SLoGin } else { 106*40fe15e0SLoGin used += (self.offset - area_base) >> MMA::PAGE_SHIFT; 107*40fe15e0SLoGin } 108*40fe15e0SLoGin } 109*40fe15e0SLoGin let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total)); 110*40fe15e0SLoGin return frame; 111*40fe15e0SLoGin } 112*40fe15e0SLoGin } 113