use alloc::alloc::{GlobalAlloc, Layout}; use core::ptr::null_mut; use x86_64::{ structures::paging::{ mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, }, VirtAddr, }; pub mod bump; pub mod fixed_size_block; pub mod linked_list; // use bump::BumpAllocator; use fixed_size_block::FixedSizeBlockAllocator; // use linked_list::LinkedListAllocator; #[global_allocator] static ALLOCATOR: Locked = Locked::new(FixedSizeBlockAllocator::new()); pub const HEAP_START: usize = 0x_4444_4444_0000; pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB pub struct Dummy; unsafe impl GlobalAlloc for Dummy { unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() } unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { panic!("dealloc should never be called") } } pub fn init_heap( mapper: &mut impl Mapper, frame_allocator: &mut impl FrameAllocator, ) -> Result<(), MapToError> { let page_range = { let heap_start = VirtAddr::new(HEAP_START as u64); let head_end = heap_start + HEAP_SIZE - 1u64; let heap_start_page = Page::containing_address(heap_start); let heap_end_page = Page::containing_address(head_end); Page::range_inclusive(heap_start_page, heap_end_page) }; for page in page_range { let frame = frame_allocator .allocate_frame() .ok_or(MapToError::FrameAllocationFailed)?; let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() }; } unsafe { ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE); } Ok(()) } pub struct Locked { inner: spin::Mutex, } impl Locked { pub const fn new(inner: A) -> Self { Locked { inner: spin::Mutex::new(inner), } } pub fn lock(&self) -> spin::MutexGuard { self.inner.lock() } } fn align_up(addr: usize, align: usize) -> usize { let remainder = addr % align; if remainder == 0 { addr // addr already aligned } else { addr - remainder + align } }