1 #![allow(dead_code)] 2 //! 这是一个关于对齐的库,提供了一些对齐的宏和函数、结构体 3 4 use core::{alloc::GlobalAlloc, fmt::Debug, ptr::Unique}; 5 6 use system_error::SystemError; 7 8 use crate::{arch::MMArch, mm::MemoryManagementArch, KERNEL_ALLOCATOR}; 9 10 /// # AlignedBox 11 /// 12 /// 一个用于分配对齐内存的结构体。分配的内存地址符合`ALIGN`的要求。 13 /// 如果类型T的对齐要求大于`ALIGN`,则采用T的对齐要求。 14 /// 15 /// ## 说明 16 /// 17 /// `ALIGN`: 对齐要求,必须是2的幂次方,且不为0,否则编译时报错 18 pub struct AlignedBox<T, const ALIGN: usize> { 19 inner: Unique<T>, 20 } 21 22 impl<T, const ALIGN: usize> AlignedBox<T, ALIGN> { 23 const LAYOUT: core::alloc::Layout = { 24 const fn max(a: usize, b: usize) -> usize { 25 if a > b { 26 a 27 } else { 28 b 29 } 30 } 31 let layout = core::alloc::Layout::from_size_align( 32 core::mem::size_of::<T>(), 33 max(ALIGN, core::mem::align_of::<T>()), 34 ); 35 36 if let Ok(layout) = layout { 37 layout 38 } else { 39 panic!("Check alignment failed at compile time.") 40 } 41 }; 42 43 /// 分配一个新的内存空间,并将其初始化为零。然后返回AlignedBox 44 /// 45 /// # Errors 46 /// 47 /// 如果分配失败,则返回`Err(SystemError::ENOMEM)` 48 #[inline(always)] 49 pub fn new_zeroed() -> Result<Self, SystemError> 50 where 51 T: SafeForZero, 52 { 53 let ptr = unsafe { KERNEL_ALLOCATOR.alloc_zeroed(Self::LAYOUT) }; 54 if ptr.is_null() { 55 return Err(SystemError::ENOMEM); 56 } else { 57 return Ok(AlignedBox { 58 inner: unsafe { Unique::new_unchecked(ptr.cast()) }, 59 }); 60 } 61 } 62 63 pub unsafe fn new_unchecked(ptr: *mut T) -> Self { 64 return AlignedBox { 65 inner: Unique::new_unchecked(ptr), 66 }; 67 } 68 } 69 70 impl<T, const ALIGN: usize> Debug for AlignedBox<T, ALIGN> { 71 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 72 return write!( 73 f, 74 "AlignedBox<{:?}, {:?}>, ptr: {:p}, size: {:}", 75 core::any::type_name::<T>(), 76 core::mem::align_of::<T>(), 77 self.inner.as_ptr(), 78 core::mem::size_of::<T>() 79 ); 80 } 81 } 82 83 impl<T, const ALIGN: usize> Drop for AlignedBox<T, ALIGN> { 84 fn drop(&mut self) { 85 unsafe { 86 // 释放 Unique 智能指针所拥有的内存,并调用类型的析构函数以清理资源 87 core::ptr::drop_in_place(self.inner.as_ptr()); 88 // dealloc memory space 89 KERNEL_ALLOCATOR.dealloc(self.inner.as_ptr().cast(), Self::LAYOUT); 90 } 91 } 92 } 93 94 impl<T, const ALIGN: usize> core::ops::Deref for AlignedBox<T, ALIGN> { 95 type Target = T; 96 97 fn deref(&self) -> &Self::Target { 98 unsafe { &*self.inner.as_ptr() } 99 } 100 } 101 102 impl<T, const ALIGN: usize> core::ops::DerefMut for AlignedBox<T, ALIGN> { 103 fn deref_mut(&mut self) -> &mut Self::Target { 104 unsafe { &mut *self.inner.as_ptr() } 105 } 106 } 107 108 impl<T: Clone + SafeForZero, const ALIGN: usize> Clone for AlignedBox<T, ALIGN> { 109 fn clone(&self) -> Self { 110 let mut new: AlignedBox<T, ALIGN> = 111 Self::new_zeroed().unwrap_or_else(|_| alloc::alloc::handle_alloc_error(Self::LAYOUT)); 112 new.clone_from(self); 113 return new; 114 } 115 } 116 117 /// 一个用于表明某个类型是安全的用于零初始化的 trait 118 /// 119 /// 该 trait 用于表明某个类型是安全的用于零初始化的,即该类型的所有位都可以被初始化为 0 而不会出现未定义行为。 120 /// 121 /// # Safety 122 /// 123 /// 该 trait 是 unsafe 的,因为它要求实现者保证该类型的所有位都可以被初始化为 0 而不会出现未定义行为。 124 pub unsafe trait SafeForZero {} 125 126 unsafe impl<const NUM: usize> SafeForZero for [u8; NUM] {} 127 128 /// 将给定的地址按照页面大小,向上对齐。 129 /// 130 /// 参数 `addr`:要对齐的地址。 131 /// 132 /// 返回值:对齐后的地址。 133 pub const fn page_align_up(addr: usize) -> usize { 134 let page_size = MMArch::PAGE_SIZE; 135 return (addr + page_size - 1) & (!(page_size - 1)); 136 } 137 138 pub const fn page_align_down(addr: usize) -> usize { 139 let page_size = MMArch::PAGE_SIZE; 140 return addr & (!(page_size - 1)); 141 } 142 143 pub const fn align_up(addr: usize, align: usize) -> usize { 144 assert!(align != 0 && align.is_power_of_two()); 145 return (addr + align - 1) & (!(align - 1)); 146 } 147 148 pub const fn align_down(addr: usize, align: usize) -> usize { 149 assert!(align != 0 && align.is_power_of_two()); 150 return addr & (!(align - 1)); 151 } 152 153 /// ## 检查是否对齐 154 /// 155 /// 检查给定的值是否对齐到给定的对齐要求。 156 /// 157 /// ## 参数 158 /// - `value`:要检查的值 159 /// - `align`:对齐要求,必须是2的幂次方,且不为0,否则运行时panic 160 /// 161 /// ## 返回值 162 /// 163 /// 如果对齐则返回`true`,否则返回`false` 164 pub fn check_aligned(value: usize, align: usize) -> bool { 165 assert!(align != 0 && align.is_power_of_two()); 166 return value & (align - 1) == 0; 167 } 168