1 use klog_types::{AllocLogItem, LogSource};
2
3 use crate::{
4 arch::mm::LockedFrameAllocator,
5 debug::klog::mm::mm_debug_log,
6 libs::align::page_align_up,
7 mm::{MMArch, MemoryManagementArch, VirtAddr},
8 };
9
10 use core::{
11 alloc::{AllocError, GlobalAlloc, Layout},
12 intrinsics::unlikely,
13 ptr::NonNull,
14 };
15
16 use super::{
17 page_frame::{FrameAllocator, PageFrameCount},
18 slab::{slab_init_state, SLABALLOCATOR},
19 };
20
21 /// 类kmalloc的分配器应当实现的trait
22 pub trait LocalAlloc {
23 #[allow(dead_code)]
local_alloc(&self, layout: Layout) -> *mut u824 unsafe fn local_alloc(&self, layout: Layout) -> *mut u8;
local_alloc_zeroed(&self, layout: Layout) -> *mut u825 unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8;
local_dealloc(&self, ptr: *mut u8, layout: Layout)26 unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout);
27 }
28
29 pub struct KernelAllocator;
30
31 impl KernelAllocator {
alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>32 unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
33 // 计算需要申请的页数,向上取整
34 let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
35 let page_frame_count = PageFrameCount::new(count);
36 let (phy_addr, allocated_frame_count) = LockedFrameAllocator
37 .allocate(page_frame_count)
38 .ok_or(AllocError)?;
39
40 let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? };
41 if unlikely(virt_addr.is_null()) {
42 return Err(AllocError);
43 }
44
45 let slice = unsafe {
46 core::slice::from_raw_parts_mut(
47 virt_addr.data() as *mut u8,
48 allocated_frame_count.data() * MMArch::PAGE_SIZE,
49 )
50 };
51 return Ok(NonNull::from(slice));
52 }
53
free_in_buddy(&self, ptr: *mut u8, layout: Layout)54 pub(super) unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) {
55 // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。
56 let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
57 let page_frame_count = PageFrameCount::new(count);
58 let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap();
59 LockedFrameAllocator.free(phy_addr, page_frame_count);
60 }
61 }
62
63 /// 为内核分配器实现LocalAlloc的trait
64 impl LocalAlloc for KernelAllocator {
local_alloc(&self, layout: Layout) -> *mut u865 unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
66 if allocator_select_condition(layout) {
67 return self
68 .alloc_in_buddy(layout)
69 .map(|x| x.as_mut_ptr())
70 .unwrap_or(core::ptr::null_mut());
71 } else {
72 if let Some(ref mut slab) = SLABALLOCATOR {
73 return slab.allocate(layout);
74 };
75 return core::ptr::null_mut();
76 }
77 }
78
local_alloc_zeroed(&self, layout: Layout) -> *mut u879 unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 {
80 if allocator_select_condition(layout) {
81 return self
82 .alloc_in_buddy(layout)
83 .map(|x| {
84 let ptr: *mut u8 = x.as_mut_ptr();
85 core::ptr::write_bytes(ptr, 0, x.len());
86 ptr
87 })
88 .unwrap_or(core::ptr::null_mut());
89 } else {
90 if let Some(ref mut slab) = SLABALLOCATOR {
91 return slab.allocate(layout);
92 };
93 return core::ptr::null_mut();
94 }
95 }
96
local_dealloc(&self, ptr: *mut u8, layout: Layout)97 unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) {
98 if allocator_select_condition(layout) || ((ptr as usize) % 4096) == 0 {
99 self.free_in_buddy(ptr, layout)
100 } else if let Some(ref mut slab) = SLABALLOCATOR {
101 slab.deallocate(ptr, layout).unwrap()
102 }
103 }
104 }
105
106 /// 为内核slab分配器实现GlobalAlloc特性
107 unsafe impl GlobalAlloc for KernelAllocator {
alloc(&self, layout: Layout) -> *mut u8108 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
109 let r = self.local_alloc_zeroed(layout);
110 if allocator_select_condition(layout) {
111 alloc_debug_log(klog_types::LogSource::Buddy, layout, r);
112 } else {
113 alloc_debug_log(klog_types::LogSource::Slab, layout, r);
114 }
115 return r;
116 }
117
alloc_zeroed(&self, layout: Layout) -> *mut u8118 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
119 let r = self.local_alloc_zeroed(layout);
120 if allocator_select_condition(layout) {
121 alloc_debug_log(klog_types::LogSource::Buddy, layout, r);
122 } else {
123 alloc_debug_log(klog_types::LogSource::Slab, layout, r);
124 }
125 return r;
126 }
127
dealloc(&self, ptr: *mut u8, layout: Layout)128 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
129 if allocator_select_condition(layout) || ((ptr as usize) % 4096) == 0 {
130 dealloc_debug_log(klog_types::LogSource::Buddy, layout, ptr);
131 } else {
132 dealloc_debug_log(klog_types::LogSource::Slab, layout, ptr);
133 }
134 self.local_dealloc(ptr, layout);
135 }
136 }
137
138 /// 判断选择buddy分配器还是slab分配器
allocator_select_condition(layout: Layout) -> bool139 fn allocator_select_condition(layout: Layout) -> bool {
140 layout.size() > 2048 || !slab_init_state()
141 }
142
alloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8)143 fn alloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8) {
144 mm_debug_log(
145 klog_types::AllocatorLogType::Alloc(AllocLogItem::new(layout, Some(ptr as usize), None)),
146 source,
147 )
148 }
149
dealloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8)150 fn dealloc_debug_log(source: LogSource, layout: Layout, ptr: *mut u8) {
151 mm_debug_log(
152 klog_types::AllocatorLogType::Free(AllocLogItem::new(layout, Some(ptr as usize), None)),
153 source,
154 )
155 }
156
157 /// 为内核slab分配器实现Allocator特性
158 // unsafe impl Allocator for KernelAllocator {
159 // fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
160 // let memory = unsafe {self.local_alloc(layout)};
161 // if memory.is_null() {
162 // Err(AllocError)
163 // } else {
164 // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
165 // Ok(unsafe { NonNull::new_unchecked(slice) })
166 // }
167 // }
168
169 // fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
170 // let memory = unsafe {self.local_alloc_zeroed(layout)};
171 // if memory.is_null() {
172 // Err(AllocError)
173 // } else {
174 // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
175 // Ok(unsafe { NonNull::new_unchecked(slice) })
176 // }
177 // }
178
179 // unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
180 // self.local_dealloc(ptr.cast().as_ptr(), layout);
181 // }
182 // }
183
184 /// 内存分配错误处理函数
185 #[cfg(target_os = "none")]
186 #[alloc_error_handler]
global_alloc_err_handler(layout: Layout) -> !187 pub fn global_alloc_err_handler(layout: Layout) -> ! {
188 panic!("global_alloc_error, layout: {:?}", layout);
189 }
190