mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
Allocator growth (#407)
Adds growth to the block allocator. - [x] No changelog update needed
This commit is contained in:
commit
3e2c57f838
|
@ -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 {
|
||||||
|
@ -37,57 +37,103 @@ impl Block {
|
||||||
.expect("too large allocation")
|
.expect("too large allocation")
|
||||||
.pad_to_align()
|
.pad_to_align()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layout() -> Layout {
|
||||||
|
Layout::new::<Block>().align_to(8).unwrap().pad_to_align()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BlockAllocatorState {
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn grow(
|
||||||
|
&self,
|
||||||
|
ptr: *mut u8,
|
||||||
|
layout: Layout,
|
||||||
|
new_layout: Layout,
|
||||||
|
) -> Option<NonNull<u8>> {
|
||||||
|
free(|key| {
|
||||||
|
self.inner
|
||||||
|
.borrow(key)
|
||||||
|
.borrow_mut()
|
||||||
|
.grow(ptr, layout, new_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,65 +156,159 @@ 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);
|
||||||
|
|
||||||
let (block_after_layout, block_after_layout_offset) = full_layout
|
let mut list_ptr = &mut self.state.first_free_block;
|
||||||
.extend(Layout::new::<Block>().align_to(8).unwrap().pad_to_align())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
free(|key| {
|
|
||||||
let mut state = self.state.borrow(key).borrow_mut();
|
|
||||||
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.
|
||||||
while let Some(mut current) = current_block {
|
loop {
|
||||||
let block_to_examine = current.as_mut();
|
match list_ptr {
|
||||||
if block_to_examine.size == full_layout.size() {
|
Some(mut current_block) => {
|
||||||
*list_ptr = block_to_examine.next;
|
if let Some(alloc) = Self::allocate_into_block(list_ptr, full_layout) {
|
||||||
return Some(current.cast());
|
return Some(alloc);
|
||||||
} else if block_to_examine.size >= block_after_layout.size() {
|
}
|
||||||
// can split block
|
list_ptr = &mut current_block.as_mut().next;
|
||||||
|
}
|
||||||
|
None => return self.new_block(layout),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// splits a block in twain
|
||||||
|
unsafe fn allocate_into_block(
|
||||||
|
reference_to_block_pointer: &mut Option<SendNonNull<Block>>,
|
||||||
|
wanted_layout: Layout,
|
||||||
|
) -> Option<NonNull<u8>> {
|
||||||
|
let (extended_layout, offset) = wanted_layout.extend(Block::layout()).unwrap();
|
||||||
|
|
||||||
|
let mut examination_block_ptr = reference_to_block_pointer.unwrap().0;
|
||||||
|
let examination_block = examination_block_ptr.as_mut();
|
||||||
|
|
||||||
|
if examination_block.size == wanted_layout.size() {
|
||||||
|
*reference_to_block_pointer = examination_block.next;
|
||||||
|
Some(examination_block_ptr.cast())
|
||||||
|
} else if examination_block.size >= extended_layout.size() {
|
||||||
let split_block = Block {
|
let split_block = Block {
|
||||||
size: block_to_examine.size - block_after_layout_offset,
|
size: examination_block.size - offset,
|
||||||
next: block_to_examine.next,
|
next: examination_block.next,
|
||||||
};
|
};
|
||||||
let split_ptr = current
|
|
||||||
|
let split_block_ptr = examination_block_ptr
|
||||||
.as_ptr()
|
.as_ptr()
|
||||||
.cast::<u8>()
|
.cast::<u8>()
|
||||||
.add(block_after_layout_offset)
|
.add(offset)
|
||||||
.cast();
|
.cast();
|
||||||
*split_ptr = split_block;
|
*split_block_ptr = split_block;
|
||||||
*list_ptr = NonNull::new(split_ptr).map(SendNonNull);
|
*reference_to_block_pointer = NonNull::new(split_block_ptr).map(SendNonNull);
|
||||||
|
|
||||||
return Some(current.cast());
|
Some(examination_block_ptr.cast())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
current_block = block_to_examine.next;
|
|
||||||
list_ptr = &mut block_to_examine.next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.new_block(layout, key)
|
pub unsafe fn grow(
|
||||||
})
|
&mut self,
|
||||||
|
ptr: *mut u8,
|
||||||
|
initial_layout: Layout,
|
||||||
|
desired_layout: Layout,
|
||||||
|
) -> Option<NonNull<u8>> {
|
||||||
|
let either_layout_initial = Block::either_layout(initial_layout);
|
||||||
|
let either_layout_desired = Block::either_layout(desired_layout);
|
||||||
|
|
||||||
|
let difference = Layout::from_size_align(
|
||||||
|
either_layout_desired.size() - either_layout_initial.size(),
|
||||||
|
either_layout_initial.align(),
|
||||||
|
)
|
||||||
|
.expect("should be able to construct difference layout");
|
||||||
|
|
||||||
|
if self.is_block_at_end(ptr, either_layout_initial) {
|
||||||
|
let _additional_space = self.inner_allocator.alloc(difference);
|
||||||
|
return NonNull::new(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
// cases
|
||||||
|
// * Our block has no free block after it.
|
||||||
|
// * Our block has a free block after that we fit in.
|
||||||
|
// * Our block has a free block after that is too small.
|
||||||
|
// * UNIMPLEMENTED Out block has a free block after that is too small but that is at the end so we can bump allocate some more space.
|
||||||
|
|
||||||
|
let next_block = self.find_first_block_after(ptr);
|
||||||
|
|
||||||
|
if let Some(list_to_block) = next_block {
|
||||||
|
let is_block_directly_after = {
|
||||||
|
if let Some(block) = list_to_block {
|
||||||
|
block.0.as_ptr() == ptr.add(either_layout_initial.size()).cast()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_block_directly_after {
|
||||||
|
if let Some(_split) = Self::allocate_into_block(list_to_block, difference) {
|
||||||
|
return NonNull::new(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.grow_copy(ptr, either_layout_initial, either_layout_desired)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn grow_copy(
|
||||||
|
&mut self,
|
||||||
|
ptr: *mut u8,
|
||||||
|
initial_layout: Layout,
|
||||||
|
desired_layout: Layout,
|
||||||
|
) -> Option<NonNull<u8>> {
|
||||||
|
let new_ptr = self.alloc(desired_layout)?;
|
||||||
|
|
||||||
|
core::ptr::copy_nonoverlapping(ptr, new_ptr.as_ptr(), initial_layout.size());
|
||||||
|
self.dealloc(ptr, initial_layout);
|
||||||
|
|
||||||
|
Some(new_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn is_block_at_end(&self, ptr: *mut u8, total_layout: Layout) -> bool {
|
||||||
|
self.inner_allocator.tip() == NonNull::new(ptr.add(total_layout.size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
/// Returns a reference to the pointer to the next block
|
||||||
|
/// Useful because you can modify what points to the block and access the block
|
||||||
|
unsafe fn find_first_block_after(
|
||||||
|
&mut self,
|
||||||
|
ptr: *mut u8,
|
||||||
|
) -> Option<&mut Option<SendNonNull<Block>>> {
|
||||||
|
let mut list_ptr = &mut self.state.first_free_block;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match list_ptr {
|
||||||
|
Some(mut current_block) => {
|
||||||
|
if current_block.as_ptr().cast() > ptr {
|
||||||
|
return Some(list_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_ptr = &mut current_block.as_mut().next;
|
||||||
|
}
|
||||||
|
None => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +340,6 @@ impl BlockAllocator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +354,24 @@ unsafe impl GlobalAlloc for BlockAllocator {
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
self.dealloc(ptr, layout);
|
self.dealloc(ptr, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
|
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||||
|
|
||||||
|
if new_size > layout.size() {
|
||||||
|
return match self.grow(ptr, layout, new_layout) {
|
||||||
|
Some(p) => p.as_ptr(),
|
||||||
|
None => core::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_ptr = GlobalAlloc::alloc(self, new_layout);
|
||||||
|
if !new_ptr.is_null() {
|
||||||
|
core::ptr::copy_nonoverlapping(ptr, new_ptr, core::cmp::min(layout.size(), new_size));
|
||||||
|
self.dealloc(ptr, layout);
|
||||||
|
}
|
||||||
|
new_ptr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Allocator for BlockAllocator {
|
unsafe impl Allocator for BlockAllocator {
|
||||||
|
@ -230,6 +387,42 @@ unsafe impl Allocator for BlockAllocator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn grow(
|
||||||
|
&self,
|
||||||
|
ptr: NonNull<u8>,
|
||||||
|
old_layout: Layout,
|
||||||
|
new_layout: Layout,
|
||||||
|
) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
|
||||||
|
match self.grow(ptr.as_ptr(), old_layout, new_layout) {
|
||||||
|
Some(p) => Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
|
||||||
|
p.as_ptr(),
|
||||||
|
new_layout.size(),
|
||||||
|
))),
|
||||||
|
None => Err(core::alloc::AllocError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn grow_zeroed(
|
||||||
|
&self,
|
||||||
|
ptr: NonNull<u8>,
|
||||||
|
old_layout: Layout,
|
||||||
|
new_layout: Layout,
|
||||||
|
) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
|
||||||
|
let new_ptr = self
|
||||||
|
.grow(ptr.as_ptr(), old_layout, new_layout)
|
||||||
|
.ok_or(core::alloc::AllocError)?;
|
||||||
|
|
||||||
|
new_ptr
|
||||||
|
.as_ptr()
|
||||||
|
.add(old_layout.size())
|
||||||
|
.write_bytes(0, new_layout.size() - old_layout.size());
|
||||||
|
|
||||||
|
Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
|
||||||
|
new_ptr.as_ptr(),
|
||||||
|
new_layout.size(),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
||||||
self.dealloc(ptr.as_ptr(), layout);
|
self.dealloc(ptr.as_ptr(), layout);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,35 +4,41 @@ 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 BumpAllocator {
|
pub(crate) struct BumpAllocatorInner {
|
||||||
current_ptr: Mutex<RefCell<Option<SendNonNull<u8>>>>,
|
current_ptr: Option<SendNonNull<u8>>,
|
||||||
start_end: Mutex<StartEnd>,
|
start_end: StartEnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BumpAllocator {
|
pub(crate) struct BumpAllocator {
|
||||||
|
inner: Mutex<RefCell<BumpAllocatorInner>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BumpAllocatorInner {
|
||||||
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)),
|
current_ptr: None,
|
||||||
start_end: Mutex::new(start_end),
|
start_end,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BumpAllocator {
|
pub fn tip(&self) -> Option<NonNull<u8>> {
|
||||||
pub fn alloc_critical(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> {
|
self.current_ptr.map(|x| x.0)
|
||||||
let mut current_ptr = self.current_ptr.borrow(cs).borrow_mut();
|
}
|
||||||
|
|
||||||
|
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 +49,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 +57,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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,4 +292,18 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_case]
|
||||||
|
fn growth_works(_gba: &mut crate::Gba) {
|
||||||
|
let mut growing_vector = Vec::with_capacity(1);
|
||||||
|
|
||||||
|
for i in 0..1000 {
|
||||||
|
growing_vector.push(i);
|
||||||
|
growing_vector.reserve_exact(i + 2);
|
||||||
|
|
||||||
|
for (idx, elem) in growing_vector.iter().enumerate() {
|
||||||
|
assert_eq!(idx, *elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
72
examples/hyperspace-roll/Cargo.lock
generated
72
examples/hyperspace-roll/Cargo.lock
generated
|
@ -176,7 +176,7 @@ version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
|
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown 0.11.2",
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -200,6 +200,12 @@ dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hound"
|
name = "hound"
|
||||||
version = "3.5.0"
|
version = "3.5.0"
|
||||||
|
@ -211,7 +217,6 @@ name = "hyperspace-roll"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"agb",
|
"agb",
|
||||||
"bare-metal",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -229,6 +234,16 @@ dependencies = [
|
||||||
"png",
|
"png",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.140"
|
version = "0.2.140"
|
||||||
|
@ -244,6 +259,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -392,6 +413,15 @@ dependencies = [
|
||||||
"syn 2.0.8",
|
"syn 2.0.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -422,11 +452,36 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -452,3 +507,12 @@ name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
71
examples/the-hat-chooses-the-wizard/Cargo.lock
generated
71
examples/the-hat-chooses-the-wizard/Cargo.lock
generated
|
@ -176,7 +176,7 @@ version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
|
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown 0.11.2",
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -200,6 +200,12 @@ dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hound"
|
name = "hound"
|
||||||
version = "3.5.0"
|
version = "3.5.0"
|
||||||
|
@ -221,6 +227,16 @@ dependencies = [
|
||||||
"png",
|
"png",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -242,6 +258,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -407,6 +429,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -446,11 +477,36 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -476,3 +532,12 @@ name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
71
examples/the-purple-night/Cargo.lock
generated
71
examples/the-purple-night/Cargo.lock
generated
|
@ -191,7 +191,7 @@ version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
|
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown 0.11.2",
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -224,6 +224,12 @@ dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hound"
|
name = "hound"
|
||||||
version = "3.5.0"
|
version = "3.5.0"
|
||||||
|
@ -245,6 +251,16 @@ dependencies = [
|
||||||
"png",
|
"png",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.140"
|
version = "0.2.140"
|
||||||
|
@ -272,6 +288,12 @@ dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -426,6 +448,15 @@ dependencies = [
|
||||||
"syn 2.0.8",
|
"syn 2.0.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -483,11 +514,36 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -514,6 +570,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xml-rs"
|
name = "xml-rs"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
|
Loading…
Reference in a new issue