#![no_std]
#![deny(missing_docs)]
extern crate alloc;
use alloc::alloc::handle_alloc_error;
use core::{
alloc::{GlobalAlloc, Layout},
cell::UnsafeCell,
ptr::NonNull,
};
use customizable_buddy::{BuddyAllocator, LinkedListBuddy, UsizeBuddy};
struct StaticCell<T> {
inner: UnsafeCell<T>,
}
unsafe impl<T> Sync for StaticCell<T> {}
impl<T> StaticCell<T> {
const fn new(value: T) -> Self {
Self {
inner: UnsafeCell::new(value),
}
}
#[inline]
fn get(&self) -> *mut T {
self.inner.get()
}
}
#[inline]
pub fn init(base_address: usize) {
heap_mut().init(
core::mem::size_of::<usize>().trailing_zeros() as _,
NonNull::new(base_address as *mut u8).unwrap(),
);
}
#[inline]
pub unsafe fn transfer(region: &'static mut [u8]) {
let ptr = NonNull::new(region.as_mut_ptr()).unwrap();
heap_mut().transfer(ptr, region.len());
}
static HEAP: StaticCell<BuddyAllocator<21, UsizeBuddy, LinkedListBuddy>> =
StaticCell::new(BuddyAllocator::new());
#[inline]
fn heap_mut() -> &'static mut BuddyAllocator<21, UsizeBuddy, LinkedListBuddy> {
unsafe { &mut *HEAP.get() }
}
struct Global;
#[global_allocator]
static GLOBAL: Global = Global;
unsafe impl GlobalAlloc for Global {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if let Ok((ptr, _)) = heap_mut().allocate_layout::<u8>(layout) {
ptr.as_ptr()
} else {
handle_alloc_error(layout)
}
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
heap_mut().deallocate_layout(NonNull::new(ptr).unwrap(), layout)
}
}