use core::{alloc::Layout, ptr::null_mut};
use irid_syscall::{io::FileDescriptor, memory::{MemoryFlags, memory_map}};
use spin::Mutex;
use talc::{TalcLock, base::{CHUNK_UNIT, Talc, binning::Binning}, min_first_heap_layout, source::Source};
use crate::eprintln;
#[global_allocator]
static ALLOCATOR: TalcLock<Mutex<()>, PageSource> = TalcLock::new(PageSource);
#[derive(Debug)]
struct PageSource;
unsafe impl Source for PageSource {
fn acquire<B: Binning>(talc: &mut Talc<Self, B>, layout: Layout) -> Result<(), ()> {
let mut required_size = layout.pad_to_align().size() + CHUNK_UNIT + CHUNK_UNIT;
if !talc.is_metadata_established() {
required_size += min_first_heap_layout::<B>().pad_to_align().size();
}
let pages = required_size.div_ceil(0x1000);
let length = pages * 0x1000;
let address = unsafe { memory_map(null_mut(), length, MemoryFlags::READABLE | MemoryFlags::WRITEABLE, FileDescriptor::MAX, 0)
.map_err(|err| {
eprintln!("allocation error: {err}");
()
}) }?;
unsafe { talc.claim(address, length).expect("failed to claim") };
Ok(())
}
}