picoalloc 5.2.0

Simple, small and fast memory allocator
Documentation
use crate::env::{abort, System};
use crate::{Env, Size};

#[inline]
fn abort_on_fail(result: usize) -> usize {
    if (result as isize) >= -4095 && (result as isize) < 0 {
        abort();
    }

    result
}

#[inline]
unsafe fn syscall2(nr: usize, a0: usize, a1: usize) -> usize {
    let r0;
    core::arch::asm!(
        "syscall",
        inlateout("rax") nr => r0,
        in("rdi") a0,
        in("rsi") a1,
        lateout("rcx") _,
        lateout("r11") _,
        options(nostack, preserves_flags)
    );
    r0
}

#[inline]
unsafe fn syscall6(nr: usize, a0: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize) -> usize {
    let r0;
    core::arch::asm!(
        "syscall",
        inlateout("rax") nr => r0,
        in("rdi") a0,
        in("rsi") a1,
        in("rdx") a2,
        in("r10") a3,
        in("r8") a4,
        in("r9") a5,
        lateout("rcx") _,
        lateout("r11") _,
        options(nostack, preserves_flags)
    );
    r0
}

impl<const SIZE: usize> Env for System<SIZE> {
    #[inline]
    fn total_space(&self) -> Size {
        const { Size::from_bytes_usize(SIZE).unwrap() }
    }

    #[inline]
    unsafe fn allocate_address_space(&mut self) -> *mut u8 {
        const SYS_MMAP: usize = 9;
        const PROT_READ: usize = 1;
        const PROT_WRITE: usize = 2;
        const MAP_PRIVATE: usize = 2;
        const MAP_ANONYMOUS: usize = 32;
        unsafe {
            let pointer = abort_on_fail(syscall6(
                SYS_MMAP,
                0,
                self.total_space().bytes() as usize,
                PROT_READ | PROT_WRITE,
                MAP_ANONYMOUS | MAP_PRIVATE,
                usize::MAX,
                0,
            ));

            core::ptr::with_exposed_provenance_mut(pointer)
        }
    }

    #[inline]
    unsafe fn expand_memory_until(&mut self, _base: *mut u8, _size: Size) -> bool {
        true
    }

    #[inline]
    unsafe fn free_address_space(&mut self, base: *mut u8) {
        const SYS_MUNMAP: usize = 11;
        unsafe {
            abort_on_fail(syscall2(SYS_MUNMAP, base.expose_provenance(), self.total_space().bytes() as usize));
        }
    }
}