tg_kernel_alloc/
lib.rs

1//! 内存分配。
2
3#![no_std]
4// #![deny(warnings)]
5#![deny(missing_docs)]
6
7extern crate alloc;
8
9use alloc::alloc::handle_alloc_error;
10use core::{
11    alloc::{GlobalAlloc, Layout},
12    ptr::NonNull,
13};
14use customizable_buddy::{BuddyAllocator, LinkedListBuddy, UsizeBuddy};
15
16/// 初始化内存分配。
17///
18/// 参数 `base_address` 表示动态内存区域的起始位置。
19///
20/// # 注意
21///
22/// 此函数必须在使用任何堆分配之前调用,且只能调用一次。
23#[inline]
24pub fn init(base_address: usize) {
25    // SAFETY: HEAP 是一个静态可变变量,此函数只在内核初始化时调用一次,
26    // 此时没有其他代码会访问 HEAP。base_address 由调用者保证是有效的堆起始地址。
27    unsafe {
28        HEAP.init(
29            core::mem::size_of::<usize>().trailing_zeros() as _,
30            NonNull::new(base_address as *mut u8).unwrap(),
31        )
32    };
33}
34
35/// 将一个内存块托管到内存分配器。
36///
37/// # Safety
38///
39/// 调用者必须确保:
40/// - `region` 内存块与已经转移到分配器的内存块都不重叠
41/// - `region` 未被其他对象引用
42/// - `region` 必须位于初始化时传入的起始位置之后
43/// - 内存块的所有权将转移到分配器
44#[inline]
45pub unsafe fn transfer(region: &'static mut [u8]) {
46    let ptr = NonNull::new(region.as_mut_ptr()).unwrap();
47    // SAFETY: 由调用者保证内存块有效且不重叠
48    HEAP.transfer(ptr, region.len());
49}
50
51/// 堆分配器。
52///
53/// 最大容量:6 + 21 + 3 = 30 -> 1 GiB。
54/// 不考虑并发使用,因此没有加锁。
55///
56/// # Safety
57///
58/// 这是一个静态可变变量,仅在单处理器环境下使用。
59/// 所有对 HEAP 的访问都通过 GlobalAlloc trait 进行,该 trait 本身是 unsafe 的。
60static mut HEAP: BuddyAllocator<21, UsizeBuddy, LinkedListBuddy> = BuddyAllocator::new();
61
62struct Global;
63
64#[global_allocator]
65static GLOBAL: Global = Global;
66
67// SAFETY: GlobalAlloc 的实现必须是 unsafe 的。
68// 此实现仅用于单处理器环境,不支持并发访问。
69unsafe impl GlobalAlloc for Global {
70    #[inline]
71    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
72        // SAFETY: 在单处理器环境下,不会有并发的分配请求。
73        // layout 的有效性由调用者(Rust 的 alloc 机制)保证。
74        if let Ok((ptr, _)) = HEAP.allocate_layout::<u8>(layout) {
75            ptr.as_ptr()
76        } else {
77            handle_alloc_error(layout)
78        }
79    }
80
81    #[inline]
82    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
83        // SAFETY: 在单处理器环境下,不会有并发的释放请求。
84        // ptr 和 layout 的有效性由调用者保证(必须是之前 alloc 返回的)。
85        HEAP.deallocate_layout(NonNull::new(ptr).unwrap(), layout)
86    }
87}