xref: /DragonOS/kernel/src/libs/align.rs (revision 7ae679ddd6481897a86523a52fad3b060254fa5b)
1bb24249fSLoGin #![allow(dead_code)]
2bb24249fSLoGin //! 这是一个关于对齐的库,提供了一些对齐的宏和函数、结构体
3bb24249fSLoGin 
4bb24249fSLoGin use core::{alloc::GlobalAlloc, fmt::Debug, ptr::Unique};
5bb24249fSLoGin 
640fe15e0SLoGin use crate::{arch::MMArch, mm::MemoryManagementArch, syscall::SystemError, KERNEL_ALLOCATOR};
7bb24249fSLoGin 
8bb24249fSLoGin /// # AlignedBox
9bb24249fSLoGin ///
10bb24249fSLoGin /// 一个用于分配对齐内存的结构体。分配的内存地址符合`ALIGN`的要求。
11bb24249fSLoGin /// 如果类型T的对齐要求大于`ALIGN`,则采用T的对齐要求。
12bb24249fSLoGin ///
13bb24249fSLoGin /// ## 说明
14bb24249fSLoGin ///
15bb24249fSLoGin /// `ALIGN`: 对齐要求,必须是2的幂次方,且不为0,否则编译时报错
16bb24249fSLoGin pub struct AlignedBox<T, const ALIGN: usize> {
17bb24249fSLoGin     inner: Unique<T>,
18bb24249fSLoGin }
19bb24249fSLoGin 
20bb24249fSLoGin impl<T, const ALIGN: usize> AlignedBox<T, ALIGN> {
21bb24249fSLoGin     const LAYOUT: core::alloc::Layout = {
22bb24249fSLoGin         const fn max(a: usize, b: usize) -> usize {
23bb24249fSLoGin             if a > b {
24bb24249fSLoGin                 a
25bb24249fSLoGin             } else {
26bb24249fSLoGin                 b
27bb24249fSLoGin             }
28bb24249fSLoGin         }
29bb24249fSLoGin         let layout = core::alloc::Layout::from_size_align(
30bb24249fSLoGin             core::mem::size_of::<T>(),
31bb24249fSLoGin             max(ALIGN, core::mem::align_of::<T>()),
32bb24249fSLoGin         );
33bb24249fSLoGin 
34bb24249fSLoGin         if let Ok(layout) = layout {
35bb24249fSLoGin             layout
36bb24249fSLoGin         } else {
37bb24249fSLoGin             panic!("Check alignment failed at compile time.")
38bb24249fSLoGin         }
39bb24249fSLoGin     };
40bb24249fSLoGin 
41bb24249fSLoGin     /// 分配一个新的内存空间,并将其初始化为零。然后返回AlignedBox
42bb24249fSLoGin     ///
43bb24249fSLoGin     /// # Errors
44bb24249fSLoGin     ///
45bb24249fSLoGin     /// 如果分配失败,则返回`Err(SystemError::ENOMEM)`
46bb24249fSLoGin     #[inline(always)]
47bb24249fSLoGin     pub fn new_zeroed() -> Result<Self, SystemError>
48bb24249fSLoGin     where
49bb24249fSLoGin         T: SafeForZero,
50bb24249fSLoGin     {
51bb24249fSLoGin         let ptr = unsafe { KERNEL_ALLOCATOR.alloc_zeroed(Self::LAYOUT) };
52bb24249fSLoGin         if ptr.is_null() {
53bb24249fSLoGin             return Err(SystemError::ENOMEM);
54bb24249fSLoGin         } else {
55bb24249fSLoGin             return Ok(AlignedBox {
56bb24249fSLoGin                 inner: unsafe { Unique::new_unchecked(ptr.cast()) },
57bb24249fSLoGin             });
58bb24249fSLoGin         }
59bb24249fSLoGin     }
601496ba7bSLoGin 
611496ba7bSLoGin     pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
621496ba7bSLoGin         return AlignedBox {
631496ba7bSLoGin             inner: Unique::new_unchecked(ptr),
641496ba7bSLoGin         };
651496ba7bSLoGin     }
66bb24249fSLoGin }
67bb24249fSLoGin 
68bb24249fSLoGin impl<T, const ALIGN: usize> Debug for AlignedBox<T, ALIGN> {
69bb24249fSLoGin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70bb24249fSLoGin         return write!(
71bb24249fSLoGin             f,
72bb24249fSLoGin             "AlignedBox<{:?}, {:?}>, ptr: {:p}, size: {:}",
73bb24249fSLoGin             core::any::type_name::<T>(),
74bb24249fSLoGin             core::mem::align_of::<T>(),
75bb24249fSLoGin             self.inner.as_ptr(),
76bb24249fSLoGin             core::mem::size_of::<T>()
77bb24249fSLoGin         );
78bb24249fSLoGin     }
79bb24249fSLoGin }
80bb24249fSLoGin 
81bb24249fSLoGin impl<T, const ALIGN: usize> Drop for AlignedBox<T, ALIGN> {
82bb24249fSLoGin     fn drop(&mut self) {
83bb24249fSLoGin         unsafe {
84bb24249fSLoGin             // 释放 Unique 智能指针所拥有的内存,并调用类型的析构函数以清理资源
85bb24249fSLoGin             core::ptr::drop_in_place(self.inner.as_ptr());
86bb24249fSLoGin             // dealloc memory space
87bb24249fSLoGin             KERNEL_ALLOCATOR.dealloc(self.inner.as_ptr().cast(), Self::LAYOUT);
88bb24249fSLoGin         }
89bb24249fSLoGin     }
90bb24249fSLoGin }
91bb24249fSLoGin 
92bb24249fSLoGin impl<T, const ALIGN: usize> core::ops::Deref for AlignedBox<T, ALIGN> {
93bb24249fSLoGin     type Target = T;
94bb24249fSLoGin 
95bb24249fSLoGin     fn deref(&self) -> &Self::Target {
96bb24249fSLoGin         unsafe { &*self.inner.as_ptr() }
97bb24249fSLoGin     }
98bb24249fSLoGin }
99bb24249fSLoGin 
100bb24249fSLoGin impl<T, const ALIGN: usize> core::ops::DerefMut for AlignedBox<T, ALIGN> {
101bb24249fSLoGin     fn deref_mut(&mut self) -> &mut Self::Target {
102bb24249fSLoGin         unsafe { &mut *self.inner.as_ptr() }
103bb24249fSLoGin     }
104bb24249fSLoGin }
105bb24249fSLoGin 
106bb24249fSLoGin impl<T: Clone + SafeForZero, const ALIGN: usize> Clone for AlignedBox<T, ALIGN> {
107bb24249fSLoGin     fn clone(&self) -> Self {
108bb24249fSLoGin         let mut new: AlignedBox<T, ALIGN> =
109bb24249fSLoGin             Self::new_zeroed().unwrap_or_else(|_| alloc::alloc::handle_alloc_error(Self::LAYOUT));
110bb24249fSLoGin         new.clone_from(self);
111bb24249fSLoGin         return new;
112bb24249fSLoGin     }
113bb24249fSLoGin }
114bb24249fSLoGin 
115bb24249fSLoGin /// 一个用于表明某个类型是安全的用于零初始化的 trait
116bb24249fSLoGin ///
117bb24249fSLoGin /// 该 trait 用于表明某个类型是安全的用于零初始化的,即该类型的所有位都可以被初始化为 0 而不会出现未定义行为。
118bb24249fSLoGin pub unsafe trait SafeForZero {}
119bb24249fSLoGin 
120bb24249fSLoGin unsafe impl<const NUM: usize> SafeForZero for [u8; NUM] {}
12140fe15e0SLoGin 
12240fe15e0SLoGin /// 将给定的地址按照页面大小,向上对齐。
12340fe15e0SLoGin ///
12440fe15e0SLoGin /// 参数 `addr`:要对齐的地址。
12540fe15e0SLoGin ///
12640fe15e0SLoGin /// 返回值:对齐后的地址。
12740fe15e0SLoGin pub fn page_align_up(addr: usize) -> usize {
12840fe15e0SLoGin     let page_size = MMArch::PAGE_SIZE;
12940fe15e0SLoGin     return (addr + page_size - 1) & (!(page_size - 1));
13040fe15e0SLoGin }
13140fe15e0SLoGin 
132*7ae679ddSLoGin pub fn page_align_down(addr: usize) -> usize {
133*7ae679ddSLoGin     let page_size = MMArch::PAGE_SIZE;
134*7ae679ddSLoGin     return addr & (!(page_size - 1));
135*7ae679ddSLoGin }
136*7ae679ddSLoGin 
13740fe15e0SLoGin /// ## 检查是否对齐
13840fe15e0SLoGin ///
13940fe15e0SLoGin /// 检查给定的值是否对齐到给定的对齐要求。
14040fe15e0SLoGin ///
14140fe15e0SLoGin /// ## 参数
14240fe15e0SLoGin /// - `value`:要检查的值
14340fe15e0SLoGin /// - `align`:对齐要求,必须是2的幂次方,且不为0,否则运行时panic
14440fe15e0SLoGin ///
14540fe15e0SLoGin /// ## 返回值
14640fe15e0SLoGin ///
14740fe15e0SLoGin /// 如果对齐则返回`true`,否则返回`false`
14840fe15e0SLoGin pub fn check_aligned(value: usize, align: usize) -> bool {
14940fe15e0SLoGin     assert!(align != 0 && align.is_power_of_two());
15040fe15e0SLoGin     return value & (align - 1) == 0;
15140fe15e0SLoGin }
152