implement allocators as zsts

This commit is contained in:
Corwin 2022-07-31 00:44:12 +01:00
parent 3ec95a0277
commit e92e8d39a5
3 changed files with 27 additions and 10 deletions

View file

@ -9,9 +9,9 @@ use alloc::boxed::Box;
#[agb::entry]
fn main(_gba: agb::Gba) -> ! {
loop {
let a = Box::new_in(1, agb::EWRAM_ALLOC);
let a = Box::new_in(1, agb::ExternalAllocator);
let b = Box::new(1);
let c = Box::new_in(3, agb::IWRAM_ALLOC);
let c = Box::new_in(3, agb::InternalAllocator);
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

@ -1,4 +1,4 @@
use core::alloc::Layout;
use core::alloc::{Allocator, Layout};
use core::ops::{Deref, DerefMut};
use core::ptr::NonNull;
@ -43,6 +43,20 @@ static GLOBAL_ALLOC: BlockAllocator = unsafe {
})
};
macro_rules! impl_zst_allocator {
($name_of_struct: ty, $name_of_static: ident) => {
unsafe impl Allocator for $name_of_struct {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
$name_of_static.allocate(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
$name_of_static.deallocate(ptr, layout)
}
}
};
}
/// This is the allocator for the External Working Ram. This is currently
/// equivalent to the Global Allocator (where things are allocated if no allocator is provided). This implements the allocator trait, so
/// is meant to be used in specifying where certain structures should be
@ -64,7 +78,9 @@ static GLOBAL_ALLOC: BlockAllocator = unsafe {
/// );
/// # }
/// ```
pub static EWRAM_ALLOC: &BlockAllocator = &GLOBAL_ALLOC;
pub struct ExternalAllocator;
impl_zst_allocator!(ExternalAllocator, GLOBAL_ALLOC);
/// This is the allocator for the Internal Working Ram. This implements the
/// allocator trait, so is meant to be used in specifying where certain
@ -86,7 +102,10 @@ pub static EWRAM_ALLOC: &BlockAllocator = &GLOBAL_ALLOC;
/// );
/// # }
/// ```
pub static IWRAM_ALLOC: &BlockAllocator = &__IWRAM_ALLOC;
pub struct InternalAllocator;
impl_zst_allocator!(InternalAllocator, __IWRAM_ALLOC);
static __IWRAM_ALLOC: BlockAllocator = unsafe {
BlockAllocator::new(StartEnd {
start: iwram_data_end,
@ -227,7 +246,7 @@ mod test {
#[test_case]
fn allocate_to_iwram_works(_gba: &mut crate::Gba) {
let a = Box::new_in(1, IWRAM_ALLOC);
let a = Box::new_in(1, InternalAllocator);
let p = &*a as *const i32;
let addr = p as usize;
assert!(

View file

@ -190,7 +190,7 @@ pub mod syscall;
/// Interactions with the internal timers
pub mod timer;
pub use {agb_alloc::EWRAM_ALLOC, agb_alloc::IWRAM_ALLOC};
pub use {agb_alloc::ExternalAllocator, agb_alloc::InternalAllocator};
#[cfg(not(any(test, feature = "testing")))]
#[panic_handler]
@ -206,8 +206,6 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
loop {}
}
static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { Gba::single_new() });
/// The Gba struct is used to control access to the Game Boy Advance's hardware in a way which makes it the
/// borrow checker's responsibility to ensure no clashes of global resources.
///
@ -245,7 +243,7 @@ impl Gba {
#[doc(hidden)]
#[must_use]
pub unsafe fn new_in_entry() -> Self {
GBASINGLE.take()
Self::single_new()
}
const unsafe fn single_new() -> Self {