1 /// @Auther: Kong 2 /// @Date: 2023-03-27 06:54:08 3 /// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs 4 /// @Description: bump allocator线性分配器 5 use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; 6 use crate::mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr, PhysMemoryArea}; 7 use core::marker::PhantomData; 8 9 /// 线性分配器 10 pub struct BumpAllocator<MMA> { 11 // 表示当前分配的物理内存的偏移量. 12 offset: usize, 13 // 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。 14 phantom: PhantomData<MMA>, 15 } 16 17 /// 为BumpAllocator实现FrameAllocator 18 impl<MMA: MemoryManagementArch> BumpAllocator<MMA> { 19 /// @brief: 创建一个线性分配器 20 /// @param Fareas 当前的内存区域 21 /// @param offset 当前的偏移量 22 /// @return 分配器本身 23 pub fn new(offset: usize) -> Self { 24 Self { 25 offset, 26 phantom: PhantomData, 27 } 28 } 29 30 // @brief 获取当前分配的物理内存的偏移量 31 pub fn offset(&self) -> usize { 32 return self.offset; 33 } 34 35 /// 返回剩余的尚未被分配的物理内存区域 36 /// 37 /// ## 返回值 38 /// 39 /// - `result_area`:剩余的尚未被分配的物理内存区域的数组 40 /// - `offset_aligned`:返回的第一个物理内存区域内,已经分配的偏移量(相对于物理内存区域的已对齐的起始地址) 41 pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> { 42 let mut offset = self.offset(); 43 44 let mut ret_offset_aligned = 0; 45 46 let mut res_cnt = 0; 47 48 let total_num = mem_block_manager().total_initial_memory_regions(); 49 // 遍历所有的物理内存区域 50 for i in 0..total_num { 51 let area = mem_block_manager().get_initial_memory_region(i).unwrap(); 52 // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整 53 // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 54 let area_base = area.area_base_aligned().data(); 55 // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整 56 // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 57 let area_end = area.area_end_aligned().data(); 58 59 // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域 60 if offset >= area_end { 61 continue; 62 } 63 64 // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base 65 if offset < area_base { 66 offset = area_base; 67 } else if offset < area_end { 68 // 将offset对齐到PAGE_SIZE 69 offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); 70 } 71 // found 72 if offset + 1 * MMA::PAGE_SIZE <= area_end { 73 for j in i..total_num { 74 let aj = mem_block_manager().get_initial_memory_region(j).unwrap(); 75 if aj.area_base_aligned() < aj.area_end_aligned() { 76 result_area[res_cnt] = aj; 77 res_cnt += 1; 78 } 79 } 80 ret_offset_aligned = offset; 81 break; 82 } 83 } 84 85 let res_cnt = unsafe { Self::arch_remain_areas(result_area, res_cnt) }; 86 if res_cnt == 0 { 87 return None; 88 } else { 89 return Some(ret_offset_aligned); 90 } 91 } 92 } 93 94 impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> { 95 /// @brief: 分配count个物理页帧 96 /// @param mut self 97 /// @param count 分配的页帧数量 98 /// @return 分配后的物理地址 99 unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 100 let mut offset = self.offset(); 101 102 let iter = mem_block_manager().to_iter(); 103 104 // 遍历所有的物理内存区域 105 for area in iter { 106 // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整 107 // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 108 let area_base = area.area_base_aligned().data(); 109 // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整 110 // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 111 let area_end = area.area_end_aligned().data(); 112 113 // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域 114 if offset >= area_end { 115 continue; 116 } 117 118 // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base 119 if offset < area_base { 120 offset = area_base; 121 } else if offset < area_end { 122 // 将offset对齐到PAGE_SIZE 123 offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); 124 } 125 // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧 126 if offset + count.data() * MMA::PAGE_SIZE <= area_end { 127 let res_page_phys = offset; 128 // 将offset增加至分配后的内存 129 self.offset = offset + count.data() * MMA::PAGE_SIZE; 130 131 return Some((PhysAddr(res_page_phys), count)); 132 } 133 } 134 return None; 135 } 136 137 unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) { 138 // TODO: 支持释放页帧 139 unimplemented!("BumpAllocator::free not implemented"); 140 } 141 /// @brief: 获取内存区域页帧的使用情况 142 /// @param self 143 /// @return 页帧的使用情况 144 unsafe fn usage(&self) -> PageFrameUsage { 145 let mut total = 0; 146 let mut used = 0; 147 let iter = mem_block_manager().to_iter(); 148 for area in iter { 149 // 将area的base地址与PAGE_SIZE对齐,对其时向上取整 150 let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 151 // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整 152 let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 153 154 total += (area_end - area_base) >> MMA::PAGE_SHIFT; 155 // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中 156 if self.offset >= area_end { 157 used += (area_end - area_base) >> MMA::PAGE_SHIFT; 158 } else if self.offset < area_base { 159 // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中 160 continue; 161 } else { 162 used += (self.offset - area_base) >> MMA::PAGE_SHIFT; 163 } 164 } 165 let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total)); 166 return frame; 167 } 168 } 169