use core::alloc::{GlobalAlloc, Layout};
use core::num::NonZeroUsize;
use core::ptr::{NonNull, null_mut};
use const_default::ConstDefault;
use rlsf::Tlsf;
use crate::sync::Mutex;
#[unsafe(no_mangle)]
extern "C" fn init() {
assert!(!wasefire_sync::executed!());
const SIZE: usize = 32768;
#[repr(align(16))]
struct Pool([u8; SIZE]);
static mut POOL: Pool = Pool([0; SIZE]);
let pool_ptr = NonNull::new(unsafe { &raw mut POOL.0 }).unwrap();
let mut allocator = ALLOCATOR.0.lock();
let size = unsafe { allocator.insert_free_block_ptr(pool_ptr) };
assert!(size > NonZeroUsize::new(SIZE / 2));
}
#[unsafe(no_mangle)]
extern "C" fn alloc(size: u32, align: u32) -> u32 {
let Ok(layout) = Layout::from_size_align(size as usize, align as usize) else { return 0 };
if size == 0 {
return 0; }
unsafe { ALLOCATOR.alloc(layout) as u32 }
}
struct Allocator(Mutex<Tlsf<'static, u16, u8, 11, 8>>);
#[global_allocator]
static ALLOCATOR: Allocator = Allocator(Mutex::new(Tlsf::DEFAULT));
unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
match self.0.lock().allocate(layout) {
None => null_mut(),
Some(x) => x.as_ptr(),
}
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { self.0.lock().deallocate(NonNull::new(ptr).unwrap(), layout.align()) }
}
}