diff --git a/agb/examples/allocation.rs b/agb/examples/allocation.rs index b1b9a8b8..87a08108 100644 --- a/agb/examples/allocation.rs +++ b/agb/examples/allocation.rs @@ -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 _); diff --git a/agb/src/agb_alloc/mod.rs b/agb/src/agb_alloc/mod.rs index 22230650..69139c54 100644 --- a/agb/src/agb_alloc/mod.rs +++ b/agb/src/agb_alloc/mod.rs @@ -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, core::alloc::AllocError> { + $name_of_static.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, 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!( diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 31657fd9..5f92bbc1 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -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 = 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 {