Skip to content

Commit 3fc35f0

Browse files
authored
Merge pull request #23 from qwandor/align
Add methods to FrameAllocator for allocating with a given alignment.
2 parents e5831c6 + 3dd509e commit 3fc35f0

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

src/frame.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use super::prev_power_of_two;
22
use alloc::collections::BTreeSet;
3+
use core::alloc::Layout;
34
use core::array;
4-
use core::cmp::min;
5+
use core::cmp::{max, min};
56
use core::ops::Range;
67

78
#[cfg(feature = "use_spin")]
@@ -71,14 +72,28 @@ impl<const ORDER: usize> FrameAllocator<ORDER> {
7172
self.total += total;
7273
}
7374

74-
/// Add a range of frame to the allocator
75+
/// Add a range of frames to the allocator.
7576
pub fn insert(&mut self, range: Range<usize>) {
7677
self.add_frame(range.start, range.end);
7778
}
7879

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.
8082
pub fn alloc(&mut self, count: usize) -> Option<usize> {
8183
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> {
8297
let class = size.trailing_zeros() as usize;
8398
for i in class..self.free_list.len() {
8499
// Find the first non-empty size class
@@ -109,14 +124,29 @@ impl<const ORDER: usize> FrameAllocator<ORDER> {
109124
None
110125
}
111126

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+
///
113129
/// 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) {
115131
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) {
116146
let class = size.trailing_zeros() as usize;
117147

118148
// Merge free buddy lists
119-
let mut current_ptr = frame;
149+
let mut current_ptr = start_frame;
120150
let mut current_class = class;
121151
while current_class < self.free_list.len() {
122152
let buddy = current_ptr ^ (1 << current_class);

src/test.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,25 @@ fn test_frame_allocator_alloc_and_free_complex() {
160160
let addr2 = frame.alloc(1).unwrap();
161161
assert_ne!(addr1, addr2);
162162
}
163+
164+
#[test]
165+
fn test_frame_allocator_aligned() {
166+
let mut frame = FrameAllocator::<32>::new();
167+
frame.add_frame(1, 64);
168+
assert_eq!(
169+
frame.alloc_aligned(Layout::from_size_align(2, 4).unwrap()),
170+
Some(4)
171+
);
172+
assert_eq!(
173+
frame.alloc_aligned(Layout::from_size_align(2, 2).unwrap()),
174+
Some(2)
175+
);
176+
assert_eq!(
177+
frame.alloc_aligned(Layout::from_size_align(2, 1).unwrap()),
178+
Some(8)
179+
);
180+
assert_eq!(
181+
frame.alloc_aligned(Layout::from_size_align(1, 16).unwrap()),
182+
Some(16)
183+
);
184+
}

0 commit comments

Comments
 (0)