extract mutable and staticable parts

This commit is contained in:
Corwin 2023-04-06 17:31:02 +01:00
parent af168f709b
commit 7030d65d9f
No known key found for this signature in database
2 changed files with 163 additions and 129 deletions

View file

@ -10,9 +10,9 @@ use core::convert::TryInto;
use core::ptr::NonNull; use core::ptr::NonNull;
use crate::interrupt::free; use crate::interrupt::free;
use bare_metal::{CriticalSection, Mutex}; use bare_metal::Mutex;
use super::bump_allocator::{BumpAllocator, StartEnd}; use super::bump_allocator::{BumpAllocatorInner, StartEnd};
use super::SendNonNull; use super::SendNonNull;
struct Block { struct Block {
@ -43,51 +43,79 @@ struct BlockAllocatorState {
first_free_block: Option<SendNonNull<Block>>, first_free_block: Option<SendNonNull<Block>>,
} }
struct BlockAllocatorInner {
inner_allocator: BumpAllocatorInner,
state: BlockAllocatorState,
}
pub struct BlockAllocator { pub struct BlockAllocator {
inner_allocator: BumpAllocator, inner: Mutex<RefCell<BlockAllocatorInner>>,
state: Mutex<RefCell<BlockAllocatorState>>,
} }
impl BlockAllocator { impl BlockAllocator {
pub(crate) const unsafe fn new(start: StartEnd) -> Self { pub(crate) const unsafe fn new(start: StartEnd) -> Self {
Self { Self {
inner_allocator: BumpAllocator::new(start), inner: Mutex::new(RefCell::new(BlockAllocatorInner::new(start))),
state: Mutex::new(RefCell::new(BlockAllocatorState {
first_free_block: None,
})),
} }
} }
#[doc(hidden)] #[doc(hidden)]
#[cfg(any(test, feature = "testing"))] #[cfg(any(test, feature = "testing"))]
pub unsafe fn number_of_blocks(&self) -> u32 { pub unsafe fn number_of_blocks(&self) -> u32 {
free(|key| { free(|key| self.inner.borrow(key).borrow_mut().number_of_blocks())
let mut state = self.state.borrow(key).borrow_mut(); }
pub unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
free(|key| self.inner.borrow(key).borrow_mut().alloc(layout))
}
pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
free(|key| self.inner.borrow(key).borrow_mut().dealloc(ptr, layout))
}
pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) {
free(|key| {
self.inner
.borrow(key)
.borrow_mut()
.dealloc_no_normalise(ptr, layout)
})
}
}
impl BlockAllocatorInner {
pub(crate) const unsafe fn new(start: StartEnd) -> Self {
Self {
inner_allocator: BumpAllocatorInner::new(start),
state: BlockAllocatorState {
first_free_block: None,
},
}
}
#[doc(hidden)]
#[cfg(any(test, feature = "testing"))]
pub unsafe fn number_of_blocks(&mut self) -> u32 {
let mut count = 0; let mut count = 0;
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut self.state.first_free_block;
while let Some(mut current) = list_ptr { while let Some(mut current) = list_ptr {
count += 1; count += 1;
list_ptr = &mut current.as_mut().next; list_ptr = &mut current.as_mut().next;
} }
count count
})
} }
/// Requests a brand new block from the inner bump allocator /// Requests a brand new block from the inner bump allocator
fn new_block(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> { fn new_block(&mut self, layout: Layout) -> Option<NonNull<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(overall_layout)
} }
/// Merges blocks together to create a normalised list /// Merges blocks together to create a normalised list
unsafe fn normalise(&self) { unsafe fn normalise(&mut self) {
free(|key| { let mut list_ptr = &mut self.state.first_free_block;
let mut state = self.state.borrow(key).borrow_mut();
let mut list_ptr = &mut state.first_free_block;
while let Some(mut current) = list_ptr { while let Some(mut current) = list_ptr {
if let Some(next_elem) = current.as_mut().next { if let Some(next_elem) = current.as_mut().next {
@ -110,10 +138,9 @@ impl BlockAllocator {
} }
list_ptr = &mut current.as_mut().next; list_ptr = &mut current.as_mut().next;
} }
});
} }
pub unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> { pub unsafe fn alloc(&mut self, layout: Layout) -> Option<NonNull<u8>> {
// find a block that this current request fits in // find a block that this current request fits in
let full_layout = Block::either_layout(layout); let full_layout = Block::either_layout(layout);
@ -121,10 +148,8 @@ impl BlockAllocator {
.extend(Layout::new::<Block>().align_to(8).unwrap().pad_to_align()) .extend(Layout::new::<Block>().align_to(8).unwrap().pad_to_align())
.unwrap(); .unwrap();
free(|key| { let mut current_block = self.state.first_free_block;
let mut state = self.state.borrow(key).borrow_mut(); let mut list_ptr = &mut self.state.first_free_block;
let mut current_block = 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 // 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 // is the exact size requested or a block that can be split into
// one with the desired size and another block header. // one with the desired size and another block header.
@ -153,22 +178,19 @@ impl BlockAllocator {
list_ptr = &mut block_to_examine.next; list_ptr = &mut block_to_examine.next;
} }
self.new_block(layout, key) self.new_block(layout)
})
} }
pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
self.dealloc_no_normalise(ptr, layout); self.dealloc_no_normalise(ptr, layout);
self.normalise(); self.normalise();
} }
pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) { pub unsafe fn dealloc_no_normalise(&mut self, ptr: *mut u8, layout: Layout) {
let new_layout = Block::either_layout(layout).pad_to_align(); let new_layout = Block::either_layout(layout).pad_to_align();
free(|key| {
let mut state = self.state.borrow(key).borrow_mut();
// note that this is a reference to a pointer // note that this is a reference to a pointer
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut self.state.first_free_block;
// This searches the free list until it finds a block further along // 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 // than the block that is being freed. The newly freed block is then
@ -200,7 +222,6 @@ impl BlockAllocator {
} }
} }
} }
});
} }
} }

View file

@ -4,35 +4,45 @@ use core::ptr::NonNull;
use super::SendNonNull; use super::SendNonNull;
use crate::interrupt::free; use crate::interrupt::free;
use bare_metal::{CriticalSection, Mutex}; use bare_metal::Mutex;
pub(crate) struct StartEnd { pub(crate) struct StartEnd {
pub start: fn() -> usize, pub start: fn() -> usize,
pub end: fn() -> usize, pub end: fn() -> usize,
} }
pub(crate) struct BumpAllocatorInner {
current_ptr: Option<SendNonNull<u8>>,
start_end: StartEnd,
}
pub(crate) struct BumpAllocator { pub(crate) struct BumpAllocator {
current_ptr: Mutex<RefCell<Option<SendNonNull<u8>>>>, inner: Mutex<RefCell<BumpAllocatorInner>>,
start_end: Mutex<StartEnd>,
} }
impl BumpAllocator { impl BumpAllocator {
pub const fn new(start_end: StartEnd) -> Self { pub const fn new(start_end: StartEnd) -> Self {
Self { Self {
current_ptr: Mutex::new(RefCell::new(None)), inner: Mutex::new(RefCell::new(BumpAllocatorInner::new(start_end))),
start_end: Mutex::new(start_end),
} }
} }
} }
impl BumpAllocator { impl BumpAllocatorInner {
pub fn alloc_critical(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> { pub const fn new(start_end: StartEnd) -> Self {
let mut current_ptr = self.current_ptr.borrow(cs).borrow_mut(); Self {
current_ptr: None,
start_end,
}
}
pub fn alloc(&mut self, layout: Layout) -> Option<NonNull<u8>> {
let current_ptr = &mut self.current_ptr;
let ptr = if let Some(c) = *current_ptr { let ptr = if let Some(c) = *current_ptr {
c.as_ptr() as usize c.as_ptr() as usize
} else { } else {
(self.start_end.borrow(cs).start)() (self.start_end.start)()
}; };
let alignment_bitmask = layout.align() - 1; let alignment_bitmask = layout.align() - 1;
@ -43,7 +53,7 @@ impl BumpAllocator {
let resulting_ptr = ptr + amount_to_add; let resulting_ptr = ptr + amount_to_add;
let new_current_ptr = resulting_ptr + layout.size(); let new_current_ptr = resulting_ptr + layout.size();
if new_current_ptr >= (self.start_end.borrow(cs).end)() { if new_current_ptr >= (self.start_end.end)() {
return None; return None;
} }
@ -51,8 +61,11 @@ impl BumpAllocator {
NonNull::new(resulting_ptr as *mut _) NonNull::new(resulting_ptr as *mut _)
} }
pub fn alloc_safe(&self, layout: Layout) -> Option<NonNull<u8>> { }
free(|key| self.alloc_critical(layout, key))
impl BumpAllocator {
fn alloc_safe(&self, layout: Layout) -> Option<NonNull<u8>> {
free(|key| self.inner.borrow(key).borrow_mut().alloc(layout))
} }
} }