Merge pull request #267 from corwinkuiper/zst-allocator

Zst allocator
This commit is contained in:
Corwin 2022-07-31 01:29:13 +01:00 committed by GitHub
commit 1e85c34187
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 14 deletions

View file

@ -9,9 +9,9 @@ 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::EWRAM_ALLOC); let a = Box::new_in(1, agb::ExternalAllocator);
let b = Box::new(1); 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!("ewram allocation made to {:?}", &*a as *const _);
agb::println!("global allocation made to {:?}", &*b as *const _); agb::println!("global allocation made to {:?}", &*b as *const _);
agb::println!("iwram allocation made to {:?}", &*c 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::ops::{Deref, DerefMut};
use core::ptr::NonNull; 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 /// 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 /// 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 /// is meant to be used in specifying where certain structures should be
@ -52,11 +66,11 @@ static GLOBAL_ALLOC: BlockAllocator = unsafe {
/// #![feature(allocator_api)] /// #![feature(allocator_api)]
/// # #![no_std] /// # #![no_std]
/// # #![no_main] /// # #![no_main]
/// # use agb::EWRAM_ALLOC; /// # use agb::ExternalAllocator;
/// # extern crate alloc; /// # extern crate alloc;
/// # use alloc::vec::Vec; /// # use alloc::vec::Vec;
/// # fn foo(gba: &mut agb::Gba) { /// # fn foo(gba: &mut agb::Gba) {
/// let mut v = Vec::new_in(EWRAM_ALLOC); /// let mut v = Vec::new_in(ExternalAllocator);
/// v.push("hello, world"); /// v.push("hello, world");
/// assert!( /// assert!(
/// (0x0200_0000..0x0204_0000).contains(&(v.as_ptr() as usize)), /// (0x0200_0000..0x0204_0000).contains(&(v.as_ptr() as usize)),
@ -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 /// This is the allocator for the Internal Working Ram. This implements the
/// allocator trait, so is meant to be used in specifying where certain /// allocator trait, so is meant to be used in specifying where certain
@ -74,11 +90,11 @@ pub static EWRAM_ALLOC: &BlockAllocator = &GLOBAL_ALLOC;
/// #![feature(allocator_api)] /// #![feature(allocator_api)]
/// # #![no_std] /// # #![no_std]
/// # #![no_main] /// # #![no_main]
/// # use agb::IWRAM_ALLOC; /// # use agb::InternalAllocator;
/// # extern crate alloc; /// # extern crate alloc;
/// # use alloc::vec::Vec; /// # use alloc::vec::Vec;
/// # fn foo(gba: &mut agb::Gba) { /// # fn foo(gba: &mut agb::Gba) {
/// let mut v = Vec::new_in(IWRAM_ALLOC); /// let mut v = Vec::new_in(InternalAllocator);
/// v.push("hello, world"); /// v.push("hello, world");
/// assert!( /// assert!(
/// (0x0300_0000..0x0300_8000).contains(&(v.as_ptr() as usize)), /// (0x0300_0000..0x0300_8000).contains(&(v.as_ptr() as usize)),
@ -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 { static __IWRAM_ALLOC: BlockAllocator = unsafe {
BlockAllocator::new(StartEnd { BlockAllocator::new(StartEnd {
start: iwram_data_end, start: iwram_data_end,
@ -227,7 +246,7 @@ mod test {
#[test_case] #[test_case]
fn allocate_to_iwram_works(_gba: &mut crate::Gba) { 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 p = &*a as *const i32;
let addr = p as usize; let addr = p as usize;
assert!( assert!(

View file

@ -190,7 +190,7 @@ pub mod syscall;
/// Interactions with the internal timers /// Interactions with the internal timers
pub mod timer; 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")))] #[cfg(not(any(test, feature = "testing")))]
#[panic_handler] #[panic_handler]
@ -206,8 +206,6 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
loop {} 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 /// 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. /// borrow checker's responsibility to ensure no clashes of global resources.
/// ///
@ -245,7 +243,7 @@ impl Gba {
#[doc(hidden)] #[doc(hidden)]
#[must_use] #[must_use]
pub unsafe fn new_in_entry() -> Self { pub unsafe fn new_in_entry() -> Self {
GBASINGLE.take() Self::single_new()
} }
const unsafe fn single_new() -> Self { const unsafe fn single_new() -> Self {