align.rs 4.9 KB

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