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 = { 24bb24249fSLoGin 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)] 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 631496ba7bSLoGin 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> { 71bb24249fSLoGin 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> { 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 97bb24249fSLoGin 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> { 103bb24249fSLoGin 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> { 109bb24249fSLoGin 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 而不会出现未定义行为。 120bb24249fSLoGin pub unsafe trait SafeForZero {} 121bb24249fSLoGin 122bb24249fSLoGin unsafe impl<const NUM: usize> SafeForZero for [u8; NUM] {} 12340fe15e0SLoGin 12440fe15e0SLoGin /// 将给定的地址按照页面大小,向上对齐。 12540fe15e0SLoGin /// 12640fe15e0SLoGin /// 参数 `addr`:要对齐的地址。 12740fe15e0SLoGin /// 12840fe15e0SLoGin /// 返回值:对齐后的地址。 129*5c4224e5SLoGin pub const fn page_align_up(addr: usize) -> usize { 13040fe15e0SLoGin let page_size = MMArch::PAGE_SIZE; 13140fe15e0SLoGin return (addr + page_size - 1) & (!(page_size - 1)); 13240fe15e0SLoGin } 13340fe15e0SLoGin 134*5c4224e5SLoGin pub const fn page_align_down(addr: usize) -> usize { 1357ae679ddSLoGin let page_size = MMArch::PAGE_SIZE; 1367ae679ddSLoGin return addr & (!(page_size - 1)); 1377ae679ddSLoGin } 1387ae679ddSLoGin 139*5c4224e5SLoGin pub const fn align_up(addr: usize, align: usize) -> usize { 140*5c4224e5SLoGin assert!(align != 0 && align.is_power_of_two()); 141*5c4224e5SLoGin return (addr + align - 1) & (!(align - 1)); 142*5c4224e5SLoGin } 143*5c4224e5SLoGin 144*5c4224e5SLoGin pub const fn align_down(addr: usize, align: usize) -> usize { 145*5c4224e5SLoGin assert!(align != 0 && align.is_power_of_two()); 146*5c4224e5SLoGin return addr & (!(align - 1)); 147*5c4224e5SLoGin } 148*5c4224e5SLoGin 14940fe15e0SLoGin /// ## 检查是否对齐 15040fe15e0SLoGin /// 15140fe15e0SLoGin /// 检查给定的值是否对齐到给定的对齐要求。 15240fe15e0SLoGin /// 15340fe15e0SLoGin /// ## 参数 15440fe15e0SLoGin /// - `value`:要检查的值 15540fe15e0SLoGin /// - `align`:对齐要求,必须是2的幂次方,且不为0,否则运行时panic 15640fe15e0SLoGin /// 15740fe15e0SLoGin /// ## 返回值 15840fe15e0SLoGin /// 15940fe15e0SLoGin /// 如果对齐则返回`true`,否则返回`false` 16040fe15e0SLoGin pub fn check_aligned(value: usize, align: usize) -> bool { 16140fe15e0SLoGin assert!(align != 0 && align.is_power_of_two()); 16240fe15e0SLoGin return value & (align - 1) == 0; 16340fe15e0SLoGin } 164