1bb24249fSLoGin #![allow(dead_code)]
2bb24249fSLoGin //! 这是一个关于对齐的库,提供了一些对齐的宏和函数、结构体
3bb24249fSLoGin
4bb24249fSLoGin use core::{alloc::GlobalAlloc, fmt::Debug, ptr::Unique};
5bb24249fSLoGin
691e9d4abSLoGin use system_error::SystemError;
791e9d4abSLoGin
891e9d4abSLoGin use crate::{arch::MMArch, mm::MemoryManagementArch, KERNEL_ALLOCATOR};
9bb24249fSLoGin
10bb24249fSLoGin /// # AlignedBox
11bb24249fSLoGin ///
12bb24249fSLoGin /// 一个用于分配对齐内存的结构体。分配的内存地址符合`ALIGN`的要求。
13bb24249fSLoGin /// 如果类型T的对齐要求大于`ALIGN`,则采用T的对齐要求。
14bb24249fSLoGin ///
15bb24249fSLoGin /// ## 说明
16bb24249fSLoGin ///
17bb24249fSLoGin /// `ALIGN`: 对齐要求,必须是2的幂次方,且不为0,否则编译时报错
18bb24249fSLoGin pub struct AlignedBox<T, const ALIGN: usize> {
19bb24249fSLoGin inner: Unique<T>,
20bb24249fSLoGin }
21bb24249fSLoGin
22bb24249fSLoGin impl<T, const ALIGN: usize> AlignedBox<T, ALIGN> {
23bb24249fSLoGin const LAYOUT: core::alloc::Layout = {
max(a: usize, b: usize) -> usize24bb24249fSLoGin const fn max(a: usize, b: usize) -> usize {
25bb24249fSLoGin if a > b {
26bb24249fSLoGin a
27bb24249fSLoGin } else {
28bb24249fSLoGin b
29bb24249fSLoGin }
30bb24249fSLoGin }
31bb24249fSLoGin let layout = core::alloc::Layout::from_size_align(
32bb24249fSLoGin core::mem::size_of::<T>(),
33bb24249fSLoGin max(ALIGN, core::mem::align_of::<T>()),
34bb24249fSLoGin );
35bb24249fSLoGin
36bb24249fSLoGin if let Ok(layout) = layout {
37bb24249fSLoGin layout
38bb24249fSLoGin } else {
39bb24249fSLoGin panic!("Check alignment failed at compile time.")
40bb24249fSLoGin }
41bb24249fSLoGin };
42bb24249fSLoGin
43bb24249fSLoGin /// 分配一个新的内存空间,并将其初始化为零。然后返回AlignedBox
44bb24249fSLoGin ///
45bb24249fSLoGin /// # Errors
46bb24249fSLoGin ///
47bb24249fSLoGin /// 如果分配失败,则返回`Err(SystemError::ENOMEM)`
48bb24249fSLoGin #[inline(always)]
new_zeroed() -> Result<Self, SystemError> where T: SafeForZero,49bb24249fSLoGin pub fn new_zeroed() -> Result<Self, SystemError>
50bb24249fSLoGin where
51bb24249fSLoGin T: SafeForZero,
52bb24249fSLoGin {
53bb24249fSLoGin let ptr = unsafe { KERNEL_ALLOCATOR.alloc_zeroed(Self::LAYOUT) };
54bb24249fSLoGin if ptr.is_null() {
55bb24249fSLoGin return Err(SystemError::ENOMEM);
56bb24249fSLoGin } else {
57bb24249fSLoGin return Ok(AlignedBox {
58bb24249fSLoGin inner: unsafe { Unique::new_unchecked(ptr.cast()) },
59bb24249fSLoGin });
60bb24249fSLoGin }
61bb24249fSLoGin }
621496ba7bSLoGin
new_unchecked(ptr: *mut T) -> Self631496ba7bSLoGin pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
641496ba7bSLoGin return AlignedBox {
651496ba7bSLoGin inner: Unique::new_unchecked(ptr),
661496ba7bSLoGin };
671496ba7bSLoGin }
68bb24249fSLoGin }
69bb24249fSLoGin
70bb24249fSLoGin impl<T, const ALIGN: usize> Debug for AlignedBox<T, ALIGN> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result71bb24249fSLoGin fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
72bb24249fSLoGin return write!(
73bb24249fSLoGin f,
74bb24249fSLoGin "AlignedBox<{:?}, {:?}>, ptr: {:p}, size: {:}",
75bb24249fSLoGin core::any::type_name::<T>(),
76bb24249fSLoGin core::mem::align_of::<T>(),
77bb24249fSLoGin self.inner.as_ptr(),
78bb24249fSLoGin core::mem::size_of::<T>()
79bb24249fSLoGin );
80bb24249fSLoGin }
81bb24249fSLoGin }
82bb24249fSLoGin
83bb24249fSLoGin impl<T, const ALIGN: usize> Drop for AlignedBox<T, ALIGN> {
drop(&mut self)84bb24249fSLoGin fn drop(&mut self) {
85bb24249fSLoGin unsafe {
86bb24249fSLoGin // 释放 Unique 智能指针所拥有的内存,并调用类型的析构函数以清理资源
87bb24249fSLoGin core::ptr::drop_in_place(self.inner.as_ptr());
88bb24249fSLoGin // dealloc memory space
89bb24249fSLoGin KERNEL_ALLOCATOR.dealloc(self.inner.as_ptr().cast(), Self::LAYOUT);
90bb24249fSLoGin }
91bb24249fSLoGin }
92bb24249fSLoGin }
93bb24249fSLoGin
94bb24249fSLoGin impl<T, const ALIGN: usize> core::ops::Deref for AlignedBox<T, ALIGN> {
95bb24249fSLoGin type Target = T;
96bb24249fSLoGin
deref(&self) -> &Self::Target97bb24249fSLoGin fn deref(&self) -> &Self::Target {
98bb24249fSLoGin unsafe { &*self.inner.as_ptr() }
99bb24249fSLoGin }
100bb24249fSLoGin }
101bb24249fSLoGin
102bb24249fSLoGin impl<T, const ALIGN: usize> core::ops::DerefMut for AlignedBox<T, ALIGN> {
deref_mut(&mut self) -> &mut Self::Target103bb24249fSLoGin fn deref_mut(&mut self) -> &mut Self::Target {
104bb24249fSLoGin unsafe { &mut *self.inner.as_ptr() }
105bb24249fSLoGin }
106bb24249fSLoGin }
107bb24249fSLoGin
108bb24249fSLoGin impl<T: Clone + SafeForZero, const ALIGN: usize> Clone for AlignedBox<T, ALIGN> {
clone(&self) -> Self109bb24249fSLoGin fn clone(&self) -> Self {
110bb24249fSLoGin let mut new: AlignedBox<T, ALIGN> =
111bb24249fSLoGin Self::new_zeroed().unwrap_or_else(|_| alloc::alloc::handle_alloc_error(Self::LAYOUT));
112bb24249fSLoGin new.clone_from(self);
113bb24249fSLoGin return new;
114bb24249fSLoGin }
115bb24249fSLoGin }
116bb24249fSLoGin
117bb24249fSLoGin /// 一个用于表明某个类型是安全的用于零初始化的 trait
118bb24249fSLoGin ///
119bb24249fSLoGin /// 该 trait 用于表明某个类型是安全的用于零初始化的,即该类型的所有位都可以被初始化为 0 而不会出现未定义行为。
120*b5b571e0SLoGin ///
121*b5b571e0SLoGin /// # Safety
122*b5b571e0SLoGin ///
123*b5b571e0SLoGin /// 该 trait 是 unsafe 的,因为它要求实现者保证该类型的所有位都可以被初始化为 0 而不会出现未定义行为。
124bb24249fSLoGin pub unsafe trait SafeForZero {}
125bb24249fSLoGin
126bb24249fSLoGin unsafe impl<const NUM: usize> SafeForZero for [u8; NUM] {}
12740fe15e0SLoGin
12840fe15e0SLoGin /// 将给定的地址按照页面大小,向上对齐。
12940fe15e0SLoGin ///
13040fe15e0SLoGin /// 参数 `addr`:要对齐的地址。
13140fe15e0SLoGin ///
13240fe15e0SLoGin /// 返回值:对齐后的地址。
page_align_up(addr: usize) -> usize1335c4224e5SLoGin pub const fn page_align_up(addr: usize) -> usize {
13440fe15e0SLoGin let page_size = MMArch::PAGE_SIZE;
13540fe15e0SLoGin return (addr + page_size - 1) & (!(page_size - 1));
13640fe15e0SLoGin }
13740fe15e0SLoGin
page_align_down(addr: usize) -> usize1385c4224e5SLoGin pub const fn page_align_down(addr: usize) -> usize {
1397ae679ddSLoGin let page_size = MMArch::PAGE_SIZE;
1407ae679ddSLoGin return addr & (!(page_size - 1));
1417ae679ddSLoGin }
1427ae679ddSLoGin
align_up(addr: usize, align: usize) -> usize1435c4224e5SLoGin pub const fn align_up(addr: usize, align: usize) -> usize {
1445c4224e5SLoGin assert!(align != 0 && align.is_power_of_two());
1455c4224e5SLoGin return (addr + align - 1) & (!(align - 1));
1465c4224e5SLoGin }
1475c4224e5SLoGin
align_down(addr: usize, align: usize) -> usize1485c4224e5SLoGin pub const fn align_down(addr: usize, align: usize) -> usize {
1495c4224e5SLoGin assert!(align != 0 && align.is_power_of_two());
1505c4224e5SLoGin return addr & (!(align - 1));
1515c4224e5SLoGin }
1525c4224e5SLoGin
15340fe15e0SLoGin /// ## 检查是否对齐
15440fe15e0SLoGin ///
15540fe15e0SLoGin /// 检查给定的值是否对齐到给定的对齐要求。
15640fe15e0SLoGin ///
15740fe15e0SLoGin /// ## 参数
15840fe15e0SLoGin /// - `value`:要检查的值
15940fe15e0SLoGin /// - `align`:对齐要求,必须是2的幂次方,且不为0,否则运行时panic
16040fe15e0SLoGin ///
16140fe15e0SLoGin /// ## 返回值
16240fe15e0SLoGin ///
16340fe15e0SLoGin /// 如果对齐则返回`true`,否则返回`false`
check_aligned(value: usize, align: usize) -> bool16440fe15e0SLoGin pub fn check_aligned(value: usize, align: usize) -> bool {
16540fe15e0SLoGin assert!(align != 0 && align.is_power_of_two());
16640fe15e0SLoGin return value & (align - 1) == 0;
16740fe15e0SLoGin }
168