|
1 | 1 | use super::prev_power_of_two;
|
2 | 2 | use alloc::collections::BTreeSet;
|
| 3 | +use core::alloc::Layout; |
3 | 4 | use core::array;
|
4 |
| -use core::cmp::min; |
| 5 | +use core::cmp::{max, min}; |
5 | 6 | use core::ops::Range;
|
6 | 7 |
|
7 | 8 | #[cfg(feature = "use_spin")]
|
@@ -71,14 +72,28 @@ impl<const ORDER: usize> FrameAllocator<ORDER> {
|
71 | 72 | self.total += total;
|
72 | 73 | }
|
73 | 74 |
|
74 |
| - /// Add a range of frame to the allocator |
| 75 | + /// Add a range of frames to the allocator. |
75 | 76 | pub fn insert(&mut self, range: Range<usize>) {
|
76 | 77 | self.add_frame(range.start, range.end);
|
77 | 78 | }
|
78 | 79 |
|
79 |
| - /// Alloc a range of frames from the allocator, return the first frame of the allocated range |
| 80 | + /// Allocate a range of frames from the allocator, returning the first frame of the allocated |
| 81 | + /// range. |
80 | 82 | pub fn alloc(&mut self, count: usize) -> Option<usize> {
|
81 | 83 | let size = count.next_power_of_two();
|
| 84 | + self.alloc_power_of_two(size) |
| 85 | + } |
| 86 | + |
| 87 | + /// Allocate a range of frames with the given size and alignment from the allocator, returning |
| 88 | + /// the first frame of the allocated range. |
| 89 | + pub fn alloc_aligned(&mut self, layout: Layout) -> Option<usize> { |
| 90 | + let size = max(layout.size().next_power_of_two(), layout.align()); |
| 91 | + self.alloc_power_of_two(size) |
| 92 | + } |
| 93 | + |
| 94 | + /// Allocate a range of frames of the given size from the allocator. The size must be a power of |
| 95 | + /// two. The allocated range will have alignment equal to the size. |
| 96 | + fn alloc_power_of_two(&mut self, size: usize) -> Option<usize> { |
82 | 97 | let class = size.trailing_zeros() as usize;
|
83 | 98 | for i in class..self.free_list.len() {
|
84 | 99 | // Find the first non-empty size class
|
@@ -109,14 +124,29 @@ impl<const ORDER: usize> FrameAllocator<ORDER> {
|
109 | 124 | None
|
110 | 125 | }
|
111 | 126 |
|
112 |
| - /// Dealloc a range of frames [frame, frame+count) from the frame allocator. |
| 127 | + /// Deallocate a range of frames [frame, frame+count) from the frame allocator. |
| 128 | + /// |
113 | 129 | /// The range should be exactly the same when it was allocated, as in heap allocator
|
114 |
| - pub fn dealloc(&mut self, frame: usize, count: usize) { |
| 130 | + pub fn dealloc(&mut self, start_frame: usize, count: usize) { |
115 | 131 | let size = count.next_power_of_two();
|
| 132 | + self.dealloc_power_of_two(start_frame, size) |
| 133 | + } |
| 134 | + |
| 135 | + /// Deallocate a range of frames which was previously allocated by [`alloc_aligned`]. |
| 136 | + /// |
| 137 | + /// The layout must be exactly the same as when it was allocated. |
| 138 | + pub fn dealloc_aligned(&mut self, start_frame: usize, layout: Layout) { |
| 139 | + let size = max(layout.size().next_power_of_two(), layout.align()); |
| 140 | + self.dealloc_power_of_two(start_frame, size) |
| 141 | + } |
| 142 | + |
| 143 | + /// Deallocate a range of frames with the given size from the allocator. The size must be a |
| 144 | + /// power of two. |
| 145 | + fn dealloc_power_of_two(&mut self, start_frame: usize, size: usize) { |
116 | 146 | let class = size.trailing_zeros() as usize;
|
117 | 147 |
|
118 | 148 | // Merge free buddy lists
|
119 |
| - let mut current_ptr = frame; |
| 149 | + let mut current_ptr = start_frame; |
120 | 150 | let mut current_class = class;
|
121 | 151 | while current_class < self.free_list.len() {
|
122 | 152 | let buddy = current_ptr ^ (1 << current_class);
|
|
0 commit comments