implement allocator api so we can allocate to (ew/iw)ram

This commit is contained in:
Corwin 2022-07-30 16:39:14 +01:00
parent 97c4115973
commit 002ccc64dd
4 changed files with 50 additions and 5 deletions

View file

@ -1,5 +1,6 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(allocator_api)]
extern crate alloc; extern crate alloc;
@ -8,7 +9,11 @@ use alloc::boxed::Box;
#[agb::entry] #[agb::entry]
fn main(_gba: agb::Gba) -> ! { fn main(_gba: agb::Gba) -> ! {
loop { loop {
let a = Box::new_in(1, agb::agb_alloc::EWRAM_ALLOC);
let b = Box::new(1); let b = Box::new(1);
agb::println!("dynamic allocation made to {:?}", &*b as *const _); let c = Box::new_in(3, agb::agb_alloc::IWRAM_ALLOC);
agb::println!("ewram allocation made to {:?}", &*a as *const _);
agb::println!("global allocation made to {:?}", &*b as *const _);
agb::println!("iwram allocation made to {:?}", &*c as *const _);
} }
} }

View file

@ -3,7 +3,7 @@
//! the linked list in order of pointer. Blocks are then merged after every //! the linked list in order of pointer. Blocks are then merged after every
//! free. //! free.
use core::alloc::{GlobalAlloc, Layout}; use core::alloc::{Allocator, GlobalAlloc, Layout};
use core::cell::RefCell; use core::cell::RefCell;
use core::convert::TryInto; use core::convert::TryInto;
@ -43,13 +43,13 @@ struct BlockAllocatorState {
first_free_block: Option<SendNonNull<Block>>, first_free_block: Option<SendNonNull<Block>>,
} }
pub(crate) struct BlockAllocator { pub struct BlockAllocator {
inner_allocator: BumpAllocator, inner_allocator: BumpAllocator,
state: Mutex<RefCell<BlockAllocatorState>>, state: Mutex<RefCell<BlockAllocatorState>>,
} }
impl BlockAllocator { impl BlockAllocator {
pub const unsafe fn new(start: StartEnd) -> Self { pub(crate) const unsafe fn new(start: StartEnd) -> Self {
Self { Self {
inner_allocator: BumpAllocator::new(start), inner_allocator: BumpAllocator::new(start),
state: Mutex::new(RefCell::new(BlockAllocatorState { state: Mutex::new(RefCell::new(BlockAllocatorState {
@ -216,3 +216,21 @@ unsafe impl GlobalAlloc for BlockAllocator {
self.dealloc(ptr, layout); self.dealloc(ptr, layout);
} }
} }
unsafe impl Allocator for BlockAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
match unsafe { self.alloc(layout) } {
None => Err(core::alloc::AllocError),
Some(p) => Ok(unsafe {
NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
p.as_ptr(),
layout.size(),
))
}),
}
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.dealloc(ptr.as_ptr(), layout);
}
}

View file

@ -33,6 +33,7 @@ impl<T> DerefMut for SendNonNull<T> {
} }
const EWRAM_END: usize = 0x0204_0000; const EWRAM_END: usize = 0x0204_0000;
const IWRAM_END: usize = 0x0300_8000;
#[global_allocator] #[global_allocator]
static GLOBAL_ALLOC: BlockAllocator = unsafe { static GLOBAL_ALLOC: BlockAllocator = unsafe {
@ -42,7 +43,17 @@ static GLOBAL_ALLOC: BlockAllocator = unsafe {
}) })
}; };
pub static EWRAM_ALLOC: &BlockAllocator = &GLOBAL_ALLOC;
pub static IWRAM_ALLOC: &BlockAllocator = &__IWRAM_ALLOC;
static __IWRAM_ALLOC: BlockAllocator = unsafe {
BlockAllocator::new(StartEnd {
start: iwram_data_end,
end: || IWRAM_END,
})
};
#[cfg(any(test, feature = "testing"))] #[cfg(any(test, feature = "testing"))]
#[cfg(test)]
pub unsafe fn number_of_blocks() -> u32 { pub unsafe fn number_of_blocks() -> u32 {
GLOBAL_ALLOC.number_of_blocks() GLOBAL_ALLOC.number_of_blocks()
} }
@ -56,6 +67,16 @@ fn alloc_error(layout: Layout) -> ! {
); );
} }
fn iwram_data_end() -> usize {
extern "C" {
static __iwram_data_end: usize;
}
// TODO: This seems completely wrong, but without the &, rust generates
// a double dereference :/. Maybe a bug in nightly?
(unsafe { &__iwram_data_end }) as *const _ as usize
}
fn data_end() -> usize { fn data_end() -> usize {
extern "C" { extern "C" {
static __ewram_data_end: usize; static __ewram_data_end: usize;

View file

@ -11,6 +11,7 @@
reexport_test_harness_main = "test_main" reexport_test_harness_main = "test_main"
)] )]
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
#![feature(allocator_api)]
#![warn(clippy::all)] #![warn(clippy::all)]
#![deny(clippy::must_use_candidate)] #![deny(clippy::must_use_candidate)]
#![deny(clippy::trivially_copy_pass_by_ref)] #![deny(clippy::trivially_copy_pass_by_ref)]
@ -161,7 +162,7 @@ pub use agb_macros::entry;
pub use agb_sound_converter::include_wav; pub use agb_sound_converter::include_wav;
extern crate alloc; extern crate alloc;
mod agb_alloc; pub mod agb_alloc;
mod agbabi; mod agbabi;
mod bitarray; mod bitarray;