xref: /DragonOS/kernel/src/mm/allocator/kernel_allocator.rs (revision ceeb2e943ca7645609920ec7ad8bfceea2b13de6)
1*ceeb2e94Slaokengwt use klog_types::{AllocLogItem, LogSource};
27b32f508SLoGin 
340fe15e0SLoGin use crate::{
440fe15e0SLoGin     arch::mm::LockedFrameAllocator,
57b32f508SLoGin     debug::klog::mm::mm_debug_log,
640fe15e0SLoGin     libs::align::page_align_up,
740fe15e0SLoGin     mm::{MMArch, MemoryManagementArch, VirtAddr},
840fe15e0SLoGin };
940fe15e0SLoGin 
1040fe15e0SLoGin use core::{
1140fe15e0SLoGin     alloc::{AllocError, GlobalAlloc, Layout},
1240fe15e0SLoGin     intrinsics::unlikely,
1340fe15e0SLoGin     ptr::NonNull,
1440fe15e0SLoGin };
1540fe15e0SLoGin 
16*ceeb2e94Slaokengwt use super::{
17*ceeb2e94Slaokengwt     page_frame::{FrameAllocator, PageFrameCount},
18*ceeb2e94Slaokengwt     slab::{slab_init_state, SLABALLOCATOR},
19*ceeb2e94Slaokengwt };
2040fe15e0SLoGin 
2140fe15e0SLoGin /// 类kmalloc的分配器应当实现的trait
2240fe15e0SLoGin pub trait LocalAlloc {
2340fe15e0SLoGin     unsafe fn local_alloc(&self, layout: Layout) -> *mut u8;
2440fe15e0SLoGin     unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8;
2540fe15e0SLoGin     unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout);
2640fe15e0SLoGin }
2740fe15e0SLoGin 
2840fe15e0SLoGin pub struct KernelAllocator;
2940fe15e0SLoGin 
3040fe15e0SLoGin impl KernelAllocator {
3140fe15e0SLoGin     unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
3240fe15e0SLoGin         // 计算需要申请的页数,向上取整
3340fe15e0SLoGin         let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
3440fe15e0SLoGin         let page_frame_count = PageFrameCount::new(count);
3540fe15e0SLoGin         let (phy_addr, allocated_frame_count) = LockedFrameAllocator
3640fe15e0SLoGin             .allocate(page_frame_count)
3740fe15e0SLoGin             .ok_or(AllocError)?;
3840fe15e0SLoGin 
3940fe15e0SLoGin         let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? };
4040fe15e0SLoGin         if unlikely(virt_addr.is_null()) {
4140fe15e0SLoGin             return Err(AllocError);
4240fe15e0SLoGin         }
4340fe15e0SLoGin 
4440fe15e0SLoGin         let slice = unsafe {
4540fe15e0SLoGin             core::slice::from_raw_parts_mut(
4640fe15e0SLoGin                 virt_addr.data() as *mut u8,
4740fe15e0SLoGin                 allocated_frame_count.data() * MMArch::PAGE_SIZE,
4840fe15e0SLoGin             )
4940fe15e0SLoGin         };
5040fe15e0SLoGin         return Ok(NonNull::from(slice));
5140fe15e0SLoGin     }
5240fe15e0SLoGin 
5340fe15e0SLoGin     unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) {
5440fe15e0SLoGin         // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。
5540fe15e0SLoGin         let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
5640fe15e0SLoGin         let page_frame_count = PageFrameCount::new(count);
5740fe15e0SLoGin         let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap();
5840fe15e0SLoGin         LockedFrameAllocator.free(phy_addr, page_frame_count);
5940fe15e0SLoGin     }
6040fe15e0SLoGin }
6140fe15e0SLoGin 
62453452ccSLoGin /// 为内核分配器实现LocalAlloc的trait
6340fe15e0SLoGin impl LocalAlloc for KernelAllocator {
6440fe15e0SLoGin     unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
65*ceeb2e94Slaokengwt         if allocator_select_condition(layout) {
6640fe15e0SLoGin             return self
6740fe15e0SLoGin                 .alloc_in_buddy(layout)
68b5b571e0SLoGin                 .map(|x| x.as_mut_ptr())
69b5b571e0SLoGin                 .unwrap_or(core::ptr::null_mut());
70*ceeb2e94Slaokengwt         } else {
71*ceeb2e94Slaokengwt             if let Some(ref mut slab) = SLABALLOCATOR {
72*ceeb2e94Slaokengwt                 return slab.allocate(layout);
73*ceeb2e94Slaokengwt             };
74*ceeb2e94Slaokengwt             return core::ptr::null_mut();
75*ceeb2e94Slaokengwt         }
7640fe15e0SLoGin     }
7740fe15e0SLoGin 
7840fe15e0SLoGin     unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 {
79*ceeb2e94Slaokengwt         if allocator_select_condition(layout) {
8040fe15e0SLoGin             return self
8140fe15e0SLoGin                 .alloc_in_buddy(layout)
8240fe15e0SLoGin                 .map(|x| {
8340fe15e0SLoGin                     let ptr: *mut u8 = x.as_mut_ptr();
8440fe15e0SLoGin                     core::ptr::write_bytes(ptr, 0, x.len());
8540fe15e0SLoGin                     ptr
8640fe15e0SLoGin                 })
87b5b571e0SLoGin                 .unwrap_or(core::ptr::null_mut());
88*ceeb2e94Slaokengwt         } else {
89*ceeb2e94Slaokengwt             if let Some(ref mut slab) = SLABALLOCATOR {
90*ceeb2e94Slaokengwt                 return slab.allocate(layout);
91*ceeb2e94Slaokengwt             };
92*ceeb2e94Slaokengwt             return core::ptr::null_mut();
93*ceeb2e94Slaokengwt         }
9440fe15e0SLoGin     }
9540fe15e0SLoGin 
9640fe15e0SLoGin     unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) {
97*ceeb2e94Slaokengwt         if allocator_select_condition(layout) || ((ptr as usize) % 4096) == 0 {
98*ceeb2e94Slaokengwt             self.free_in_buddy(ptr, layout)
99*ceeb2e94Slaokengwt         } else if let Some(ref mut slab) = SLABALLOCATOR {
100*ceeb2e94Slaokengwt             slab.deallocate(ptr, layout).unwrap()
101*ceeb2e94Slaokengwt         }
10240fe15e0SLoGin     }
10340fe15e0SLoGin }
10440fe15e0SLoGin 
10540fe15e0SLoGin /// 为内核slab分配器实现GlobalAlloc特性
10640fe15e0SLoGin unsafe impl GlobalAlloc for KernelAllocator {
10740fe15e0SLoGin     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
108453452ccSLoGin         let r = self.local_alloc_zeroed(layout);
109*ceeb2e94Slaokengwt         if allocator_select_condition(layout) {
110*ceeb2e94Slaokengwt             alloc_debug_log(klog_types::LogSource::Buddy, layout, r);
111*ceeb2e94Slaokengwt         } else {
112*ceeb2e94Slaokengwt             alloc_debug_log(klog_types::LogSource::Slab, layout, r);
113*ceeb2e94Slaokengwt         }
1147b32f508SLoGin         return r;
11540fe15e0SLoGin     }
11640fe15e0SLoGin 
11740fe15e0SLoGin     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
1187b32f508SLoGin         let r = self.local_alloc_zeroed(layout);
119*ceeb2e94Slaokengwt         if allocator_select_condition(layout) {
120*ceeb2e94Slaokengwt             alloc_debug_log(klog_types::LogSource::Buddy, layout, r);
121*ceeb2e94Slaokengwt         } else {
122*ceeb2e94Slaokengwt             alloc_debug_log(klog_types::LogSource::Slab, layout, r);
123*ceeb2e94Slaokengwt         }
1247b32f508SLoGin         return r;
12540fe15e0SLoGin     }
12640fe15e0SLoGin 
12740fe15e0SLoGin     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
128*ceeb2e94Slaokengwt         if allocator_select_condition(layout) || ((ptr as usize) % 4096) == 0 {
129*ceeb2e94Slaokengwt             dealloc_debug_log(klog_types::LogSource::Buddy, layout, ptr);
130*ceeb2e94Slaokengwt         } else {
131*ceeb2e94Slaokengwt             dealloc_debug_log(klog_types::LogSource::Slab, layout, ptr);
132*ceeb2e94Slaokengwt         }
13340fe15e0SLoGin         self.local_dealloc(ptr, layout);
13440fe15e0SLoGin     }
13540fe15e0SLoGin }
13640fe15e0SLoGin 
137*ceeb2e94Slaokengwt /// 判断选择buddy分配器还是slab分配器
138*ceeb2e94Slaokengwt fn allocator_select_condition(layout: Layout) -> bool {
139*ceeb2e94Slaokengwt     layout.size() > 2048 || !slab_init_state()
140*ceeb2e94Slaokengwt }
141*ceeb2e94Slaokengwt 
142*ceeb2e94Slaokengwt fn alloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8) {
143*ceeb2e94Slaokengwt     mm_debug_log(
144*ceeb2e94Slaokengwt         klog_types::AllocatorLogType::Alloc(AllocLogItem::new(layout, Some(ptr as usize), None)),
145*ceeb2e94Slaokengwt         source,
146*ceeb2e94Slaokengwt     )
147*ceeb2e94Slaokengwt }
148*ceeb2e94Slaokengwt 
149*ceeb2e94Slaokengwt fn dealloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8) {
150*ceeb2e94Slaokengwt     mm_debug_log(
151*ceeb2e94Slaokengwt         klog_types::AllocatorLogType::Free(AllocLogItem::new(layout, Some(ptr as usize), None)),
152*ceeb2e94Slaokengwt         source,
153*ceeb2e94Slaokengwt     )
154*ceeb2e94Slaokengwt }
155*ceeb2e94Slaokengwt 
15640314b30SXiaoye Zheng /// 为内核slab分配器实现Allocator特性
15740314b30SXiaoye Zheng // unsafe impl Allocator for KernelAllocator {
15840314b30SXiaoye Zheng //     fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
15940314b30SXiaoye Zheng //         let memory = unsafe {self.local_alloc(layout)};
16040314b30SXiaoye Zheng //         if memory.is_null() {
16140314b30SXiaoye Zheng //             Err(AllocError)
16240314b30SXiaoye Zheng //         } else {
16340314b30SXiaoye Zheng //             let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
16440314b30SXiaoye Zheng //             Ok(unsafe { NonNull::new_unchecked(slice) })
16540314b30SXiaoye Zheng //         }
16640314b30SXiaoye Zheng //     }
16740314b30SXiaoye Zheng 
16840314b30SXiaoye Zheng //     fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
16940314b30SXiaoye Zheng //         let memory = unsafe {self.local_alloc_zeroed(layout)};
17040314b30SXiaoye Zheng //         if memory.is_null() {
17140314b30SXiaoye Zheng //             Err(AllocError)
17240314b30SXiaoye Zheng //         } else {
17340314b30SXiaoye Zheng //             let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
17440314b30SXiaoye Zheng //             Ok(unsafe { NonNull::new_unchecked(slice) })
17540314b30SXiaoye Zheng //         }
17640314b30SXiaoye Zheng //     }
17740314b30SXiaoye Zheng 
17840314b30SXiaoye Zheng //     unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
17940314b30SXiaoye Zheng //         self.local_dealloc(ptr.cast().as_ptr(), layout);
18040314b30SXiaoye Zheng //     }
18140314b30SXiaoye Zheng // }
18240314b30SXiaoye Zheng 
18340fe15e0SLoGin /// 内存分配错误处理函数
184fba56231SLoGin #[cfg(target_os = "none")]
18540fe15e0SLoGin #[alloc_error_handler]
18640fe15e0SLoGin pub fn global_alloc_err_handler(layout: Layout) -> ! {
18740fe15e0SLoGin     panic!("global_alloc_error, layout: {:?}", layout);
18840fe15e0SLoGin }
189