1ceeb2e94Slaokengwt 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
16ceeb2e94Slaokengwt use super::{
17ceeb2e94Slaokengwt page_frame::{FrameAllocator, PageFrameCount},
18ceeb2e94Slaokengwt slab::{slab_init_state, SLABALLOCATOR},
19ceeb2e94Slaokengwt };
2040fe15e0SLoGin
2140fe15e0SLoGin /// 类kmalloc的分配器应当实现的trait
2240fe15e0SLoGin pub trait LocalAlloc {
23*bd70d2d1SLoGin #[allow(dead_code)]
local_alloc(&self, layout: Layout) -> *mut u82440fe15e0SLoGin unsafe fn local_alloc(&self, layout: Layout) -> *mut u8;
local_alloc_zeroed(&self, layout: Layout) -> *mut u82540fe15e0SLoGin unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8;
local_dealloc(&self, ptr: *mut u8, layout: Layout)2640fe15e0SLoGin unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout);
2740fe15e0SLoGin }
2840fe15e0SLoGin
2940fe15e0SLoGin pub struct KernelAllocator;
3040fe15e0SLoGin
3140fe15e0SLoGin impl KernelAllocator {
alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>3240fe15e0SLoGin unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
3340fe15e0SLoGin // 计算需要申请的页数,向上取整
3440fe15e0SLoGin let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
3540fe15e0SLoGin let page_frame_count = PageFrameCount::new(count);
3640fe15e0SLoGin let (phy_addr, allocated_frame_count) = LockedFrameAllocator
3740fe15e0SLoGin .allocate(page_frame_count)
3840fe15e0SLoGin .ok_or(AllocError)?;
3940fe15e0SLoGin
4040fe15e0SLoGin let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? };
4140fe15e0SLoGin if unlikely(virt_addr.is_null()) {
4240fe15e0SLoGin return Err(AllocError);
4340fe15e0SLoGin }
4440fe15e0SLoGin
4540fe15e0SLoGin let slice = unsafe {
4640fe15e0SLoGin core::slice::from_raw_parts_mut(
4740fe15e0SLoGin virt_addr.data() as *mut u8,
4840fe15e0SLoGin allocated_frame_count.data() * MMArch::PAGE_SIZE,
4940fe15e0SLoGin )
5040fe15e0SLoGin };
5140fe15e0SLoGin return Ok(NonNull::from(slice));
5240fe15e0SLoGin }
5340fe15e0SLoGin
free_in_buddy(&self, ptr: *mut u8, layout: Layout)5440fe15e0SLoGin unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) {
5540fe15e0SLoGin // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。
5640fe15e0SLoGin let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
5740fe15e0SLoGin let page_frame_count = PageFrameCount::new(count);
5840fe15e0SLoGin let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap();
5940fe15e0SLoGin LockedFrameAllocator.free(phy_addr, page_frame_count);
6040fe15e0SLoGin }
6140fe15e0SLoGin }
6240fe15e0SLoGin
63453452ccSLoGin /// 为内核分配器实现LocalAlloc的trait
6440fe15e0SLoGin impl LocalAlloc for KernelAllocator {
local_alloc(&self, layout: Layout) -> *mut u86540fe15e0SLoGin unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
66ceeb2e94Slaokengwt if allocator_select_condition(layout) {
6740fe15e0SLoGin return self
6840fe15e0SLoGin .alloc_in_buddy(layout)
69b5b571e0SLoGin .map(|x| x.as_mut_ptr())
70b5b571e0SLoGin .unwrap_or(core::ptr::null_mut());
71ceeb2e94Slaokengwt } else {
72ceeb2e94Slaokengwt if let Some(ref mut slab) = SLABALLOCATOR {
73ceeb2e94Slaokengwt return slab.allocate(layout);
74ceeb2e94Slaokengwt };
75ceeb2e94Slaokengwt return core::ptr::null_mut();
76ceeb2e94Slaokengwt }
7740fe15e0SLoGin }
7840fe15e0SLoGin
local_alloc_zeroed(&self, layout: Layout) -> *mut u87940fe15e0SLoGin unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 {
80ceeb2e94Slaokengwt if allocator_select_condition(layout) {
8140fe15e0SLoGin return self
8240fe15e0SLoGin .alloc_in_buddy(layout)
8340fe15e0SLoGin .map(|x| {
8440fe15e0SLoGin let ptr: *mut u8 = x.as_mut_ptr();
8540fe15e0SLoGin core::ptr::write_bytes(ptr, 0, x.len());
8640fe15e0SLoGin ptr
8740fe15e0SLoGin })
88b5b571e0SLoGin .unwrap_or(core::ptr::null_mut());
89ceeb2e94Slaokengwt } else {
90ceeb2e94Slaokengwt if let Some(ref mut slab) = SLABALLOCATOR {
91ceeb2e94Slaokengwt return slab.allocate(layout);
92ceeb2e94Slaokengwt };
93ceeb2e94Slaokengwt return core::ptr::null_mut();
94ceeb2e94Slaokengwt }
9540fe15e0SLoGin }
9640fe15e0SLoGin
local_dealloc(&self, ptr: *mut u8, layout: Layout)9740fe15e0SLoGin unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) {
98ceeb2e94Slaokengwt if allocator_select_condition(layout) || ((ptr as usize) % 4096) == 0 {
99ceeb2e94Slaokengwt self.free_in_buddy(ptr, layout)
100ceeb2e94Slaokengwt } else if let Some(ref mut slab) = SLABALLOCATOR {
101ceeb2e94Slaokengwt slab.deallocate(ptr, layout).unwrap()
102ceeb2e94Slaokengwt }
10340fe15e0SLoGin }
10440fe15e0SLoGin }
10540fe15e0SLoGin
10640fe15e0SLoGin /// 为内核slab分配器实现GlobalAlloc特性
10740fe15e0SLoGin unsafe impl GlobalAlloc for KernelAllocator {
alloc(&self, layout: Layout) -> *mut u810840fe15e0SLoGin unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
109453452ccSLoGin let r = self.local_alloc_zeroed(layout);
110ceeb2e94Slaokengwt if allocator_select_condition(layout) {
111ceeb2e94Slaokengwt alloc_debug_log(klog_types::LogSource::Buddy, layout, r);
112ceeb2e94Slaokengwt } else {
113ceeb2e94Slaokengwt alloc_debug_log(klog_types::LogSource::Slab, layout, r);
114ceeb2e94Slaokengwt }
1157b32f508SLoGin return r;
11640fe15e0SLoGin }
11740fe15e0SLoGin
alloc_zeroed(&self, layout: Layout) -> *mut u811840fe15e0SLoGin unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
1197b32f508SLoGin let r = self.local_alloc_zeroed(layout);
120ceeb2e94Slaokengwt if allocator_select_condition(layout) {
121ceeb2e94Slaokengwt alloc_debug_log(klog_types::LogSource::Buddy, layout, r);
122ceeb2e94Slaokengwt } else {
123ceeb2e94Slaokengwt alloc_debug_log(klog_types::LogSource::Slab, layout, r);
124ceeb2e94Slaokengwt }
1257b32f508SLoGin return r;
12640fe15e0SLoGin }
12740fe15e0SLoGin
dealloc(&self, ptr: *mut u8, layout: Layout)12840fe15e0SLoGin unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
129ceeb2e94Slaokengwt if allocator_select_condition(layout) || ((ptr as usize) % 4096) == 0 {
130ceeb2e94Slaokengwt dealloc_debug_log(klog_types::LogSource::Buddy, layout, ptr);
131ceeb2e94Slaokengwt } else {
132ceeb2e94Slaokengwt dealloc_debug_log(klog_types::LogSource::Slab, layout, ptr);
133ceeb2e94Slaokengwt }
13440fe15e0SLoGin self.local_dealloc(ptr, layout);
13540fe15e0SLoGin }
13640fe15e0SLoGin }
13740fe15e0SLoGin
138ceeb2e94Slaokengwt /// 判断选择buddy分配器还是slab分配器
allocator_select_condition(layout: Layout) -> bool139ceeb2e94Slaokengwt fn allocator_select_condition(layout: Layout) -> bool {
140ceeb2e94Slaokengwt layout.size() > 2048 || !slab_init_state()
141ceeb2e94Slaokengwt }
142ceeb2e94Slaokengwt
alloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8)143ceeb2e94Slaokengwt fn alloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8) {
144ceeb2e94Slaokengwt mm_debug_log(
145ceeb2e94Slaokengwt klog_types::AllocatorLogType::Alloc(AllocLogItem::new(layout, Some(ptr as usize), None)),
146ceeb2e94Slaokengwt source,
147ceeb2e94Slaokengwt )
148ceeb2e94Slaokengwt }
149ceeb2e94Slaokengwt
dealloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8)150ceeb2e94Slaokengwt fn dealloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8) {
151ceeb2e94Slaokengwt mm_debug_log(
152ceeb2e94Slaokengwt klog_types::AllocatorLogType::Free(AllocLogItem::new(layout, Some(ptr as usize), None)),
153ceeb2e94Slaokengwt source,
154ceeb2e94Slaokengwt )
155ceeb2e94Slaokengwt }
156ceeb2e94Slaokengwt
15740314b30SXiaoye Zheng /// 为内核slab分配器实现Allocator特性
15840314b30SXiaoye Zheng // unsafe impl Allocator for KernelAllocator {
15940314b30SXiaoye Zheng // fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
16040314b30SXiaoye Zheng // let memory = unsafe {self.local_alloc(layout)};
16140314b30SXiaoye Zheng // if memory.is_null() {
16240314b30SXiaoye Zheng // Err(AllocError)
16340314b30SXiaoye Zheng // } else {
16440314b30SXiaoye Zheng // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
16540314b30SXiaoye Zheng // Ok(unsafe { NonNull::new_unchecked(slice) })
16640314b30SXiaoye Zheng // }
16740314b30SXiaoye Zheng // }
16840314b30SXiaoye Zheng
16940314b30SXiaoye Zheng // fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
17040314b30SXiaoye Zheng // let memory = unsafe {self.local_alloc_zeroed(layout)};
17140314b30SXiaoye Zheng // if memory.is_null() {
17240314b30SXiaoye Zheng // Err(AllocError)
17340314b30SXiaoye Zheng // } else {
17440314b30SXiaoye Zheng // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
17540314b30SXiaoye Zheng // Ok(unsafe { NonNull::new_unchecked(slice) })
17640314b30SXiaoye Zheng // }
17740314b30SXiaoye Zheng // }
17840314b30SXiaoye Zheng
17940314b30SXiaoye Zheng // unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
18040314b30SXiaoye Zheng // self.local_dealloc(ptr.cast().as_ptr(), layout);
18140314b30SXiaoye Zheng // }
18240314b30SXiaoye Zheng // }
18340314b30SXiaoye Zheng
18440fe15e0SLoGin /// 内存分配错误处理函数
185fba56231SLoGin #[cfg(target_os = "none")]
18640fe15e0SLoGin #[alloc_error_handler]
global_alloc_err_handler(layout: Layout) -> !18740fe15e0SLoGin pub fn global_alloc_err_handler(layout: Layout) -> ! {
18840fe15e0SLoGin panic!("global_alloc_error, layout: {:?}", layout);
18940fe15e0SLoGin }
190