mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-26 00:56:38 +11:00
add some explanatory comments
This commit is contained in:
parent
08e07a0d37
commit
fc6acda14d
1 changed files with 17 additions and 0 deletions
|
@ -10,12 +10,19 @@ use bare_metal::{CriticalSection, Mutex};
|
||||||
use super::bump_allocator::BumpAllocator;
|
use super::bump_allocator::BumpAllocator;
|
||||||
use super::SendNonNull;
|
use super::SendNonNull;
|
||||||
|
|
||||||
|
/// The block allocator works by maintaining a linked list of unused blocks and
|
||||||
|
/// requesting new blocks using a bump allocator. Freed blocks are inserted into
|
||||||
|
/// the linked list in order of pointer. Blocks are then merged after every
|
||||||
|
/// free.
|
||||||
|
|
||||||
struct Block {
|
struct Block {
|
||||||
size: usize,
|
size: usize,
|
||||||
next: Option<SendNonNull<Block>>,
|
next: Option<SendNonNull<Block>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
|
/// Returns the layout of either the block or the wanted layout aligned to
|
||||||
|
/// the maximum alignment used (double word).
|
||||||
pub fn either_layout(layout: Layout) -> Layout {
|
pub fn either_layout(layout: Layout) -> Layout {
|
||||||
let block_layout = Layout::new::<Block>();
|
let block_layout = Layout::new::<Block>();
|
||||||
let aligned_to = layout
|
let aligned_to = layout
|
||||||
|
@ -67,11 +74,13 @@ impl BlockAllocator {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Requests a brand new block from the inner bump allocator
|
||||||
fn new_block(&self, layout: Layout, cs: &CriticalSection) -> *mut u8 {
|
fn new_block(&self, layout: Layout, cs: &CriticalSection) -> *mut u8 {
|
||||||
let overall_layout = Block::either_layout(layout);
|
let overall_layout = Block::either_layout(layout);
|
||||||
self.inner_allocator.alloc_critical(overall_layout, cs)
|
self.inner_allocator.alloc_critical(overall_layout, cs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merges blocks together to create a normalised list
|
||||||
unsafe fn normalise(&self) {
|
unsafe fn normalise(&self) {
|
||||||
free(|key| {
|
free(|key| {
|
||||||
let mut state = self.state.borrow(*key).borrow_mut();
|
let mut state = self.state.borrow(*key).borrow_mut();
|
||||||
|
@ -116,6 +125,9 @@ unsafe impl GlobalAlloc for BlockAllocator {
|
||||||
let mut state = self.state.borrow(*key).borrow_mut();
|
let mut state = self.state.borrow(*key).borrow_mut();
|
||||||
let mut current_block = state.first_free_block;
|
let mut current_block = state.first_free_block;
|
||||||
let mut list_ptr = &mut state.first_free_block;
|
let mut list_ptr = &mut state.first_free_block;
|
||||||
|
// This iterates the free list until it either finds a block that
|
||||||
|
// is the exact size requested or a block that can be split into
|
||||||
|
// one with the desired size and another block header.
|
||||||
while let Some(mut curr) = current_block {
|
while let Some(mut curr) = current_block {
|
||||||
let curr_block = curr.as_mut();
|
let curr_block = curr.as_mut();
|
||||||
if curr_block.size == full_layout.size() {
|
if curr_block.size == full_layout.size() {
|
||||||
|
@ -150,8 +162,13 @@ unsafe impl GlobalAlloc for BlockAllocator {
|
||||||
free(|key| {
|
free(|key| {
|
||||||
let mut state = self.state.borrow(*key).borrow_mut();
|
let mut state = self.state.borrow(*key).borrow_mut();
|
||||||
|
|
||||||
|
// note that this is a reference to a pointer
|
||||||
let mut list_ptr = &mut state.first_free_block;
|
let mut list_ptr = &mut state.first_free_block;
|
||||||
|
|
||||||
|
// This searches the free list until it finds a block further along
|
||||||
|
// than the block that is being freed. The newly freed block is then
|
||||||
|
// inserted before this block. If the end of the list is reached
|
||||||
|
// then the block is placed at the end with no new block after it.
|
||||||
loop {
|
loop {
|
||||||
match list_ptr {
|
match list_ptr {
|
||||||
Some(mut current_block) => {
|
Some(mut current_block) => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue