Skip to content

Commit 8b72531

Browse files
committed
feat: add fixed size block allocator
1 parent 4876cbe commit 8b72531

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

kernel/src/allocator.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ use x86_64::{
88
},
99
};
1010

11-
use crate::allocator::{bump::BumpAllocator, linked_list::LinkedListAllocator};
11+
use crate::allocator::{
12+
bump::BumpAllocator, fixed_size_block::FixedSizeBlockAllocator,
13+
linked_list::LinkedListAllocator,
14+
};
1215

1316
pub mod bump;
17+
pub mod fixed_size_block;
1418
pub mod linked_list;
1519

1620
pub const HEAP_START: usize = 0x_4444_4444_0000;
@@ -49,7 +53,7 @@ pub fn init_heap(
4953
}
5054

5155
#[global_allocator]
52-
static ALLOCATOR: LockedHeap = Locked::new(LinkedListAllocator::new());
56+
static ALLOCATOR: LockedHeap = Locked::new(FixedSizeBlockAllocator::new());
5357

5458
pub struct Dummy;
5559

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use super::Locked;
2+
use core::alloc::{GlobalAlloc, Layout};
3+
4+
/// Fixed size block allocator
5+
///
6+
/// Advantages of this allocator:
7+
/// - O(1) time complexity
8+
///
9+
/// Fallback: Linked list allocator
10+
11+
/// Sizes are also used for alignments, so they need to be powers of 2.
12+
const BLOCK_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048];
13+
14+
struct ListNode {
15+
next: Option<&'static mut ListNode>,
16+
}
17+
18+
pub struct FixedSizeBlockAllocator {
19+
list_heads: [Option<&'static mut ListNode>; BLOCK_SIZES.len()],
20+
fallback_allocator: linked_list_allocator::Heap,
21+
}
22+
23+
impl FixedSizeBlockAllocator {
24+
pub const fn new() -> Self {
25+
const EMPTY: Option<&'static mut ListNode> = None;
26+
27+
FixedSizeBlockAllocator {
28+
list_heads: [EMPTY; BLOCK_SIZES.len()],
29+
// FIXME: Use the allocator that we created.
30+
fallback_allocator: linked_list_allocator::Heap::empty(),
31+
}
32+
}
33+
34+
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
35+
unsafe {
36+
self.fallback_allocator.init(heap_start, heap_size);
37+
}
38+
}
39+
40+
fn fallback_alloc(&mut self, layout: Layout) -> *mut u8 {
41+
match self.fallback_allocator.allocate_first_fit(layout) {
42+
Ok(ptr) => ptr.as_ptr(),
43+
Err(_) => ptr::null_ptr(),
44+
}
45+
}
46+
}
47+
48+
fn list_index(layout: &Layout) -> Option<usize> {
49+
let required_block_size = layout.size().max(layout.align());
50+
51+
BLOCK_SIZES.iter().position(|&s| s >= required_block_size)
52+
}
53+
54+
unsafe impl GlobalAlloc for Locked<FixedSizeBlockAllocator> {
55+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
56+
let mut allocator = self.lock();
57+
58+
match list_index(&layout) {
59+
Some(index) => match allocator.list_heads[index].take() {
60+
Some(node) => {
61+
allocator.list_heads[index] = node.next.take();
62+
node as *mut ListNode as *mut u8
63+
}
64+
65+
None => {
66+
let block_size = BLOCK_SIZES[index];
67+
// `from_size_align` requires an alignment in powers of two.
68+
let block_align = block_size;
69+
70+
let layout = Layout::from_size_align(block_size, block_align).unwrap();
71+
allocator.fallback_alloc(layout)
72+
}
73+
},
74+
75+
None => allocator.fallback_alloc(layout),
76+
}
77+
}
78+
79+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
80+
let mut allocator = self.lock();
81+
82+
match list_index(&layout) {
83+
Some(index) => {
84+
let new_node = ListNode {
85+
next: allocator.list_heads[index].take(),
86+
};
87+
88+
assert!(mem::size_of::<ListNode>() <= BLOCK_SIZES[index]);
89+
assert!(mem::size_of::<ListNode>() <= BLOCK_SIZES[index]);
90+
91+
let new_node_ptr = ptr as *mut ListNode;
92+
93+
unsafe {
94+
new_node_ptr.write(new_node);
95+
allocator.list_heads[index] = Some(&mut *new_node_ptr);
96+
}
97+
}
98+
99+
None => {
100+
let ptr = NonNull::new(ptr).unwrap();
101+
102+
unsafe {
103+
allocator.fallback_allocator.deallocate(ptr, layout);
104+
}
105+
}
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)