#![allow(static_mut_refs)]
use core::alloc::Layout;
use core::ffi::c_void;
use core::ptr;
use crate::syscall;
#[cfg(feature = "panic-on-realloc")]
static mut IS_FIRST_REALLOC: bool = true;
#[cfg(feature = "print-allocations")]
use crate::common::utils::to_ascii;
const ALIGN: usize = 16;
const ARENA_SIZE: usize = 1024 * 1024;
const PAGE_SIZE: usize = 4096;
struct Arena {
base: *mut u8,
size: usize,
offset: usize,
}
static mut ARENA: Arena = Arena {
base: ptr::null_mut(),
size: 0,
offset: 0,
};
pub struct ArenaAlloc;
#[inline]
unsafe fn map_chunk(min_size: usize) -> Arena {
let size = min_size.max(ARENA_SIZE).next_multiple_of(PAGE_SIZE);
let base = syscall::mmap(
ptr::null_mut(),
size,
syscall::PROT_READ | syscall::PROT_WRITE,
syscall::MAP_PRIVATE | syscall::MAP_ANONYMOUS,
-1,
0,
) as *mut u8;
if base.is_null() {
let msg = c"mmap failed in common/alloc.rs\n";
syscall::write(2, msg.as_ptr() as *const c_void, msg.count_bytes());
syscall::exit(1);
}
Arena {
base,
size,
offset: 0,
}
}
unsafe impl core::alloc::GlobalAlloc for ArenaAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
#[cfg(feature = "print-allocations")]
{
let mut buf = [0u8; 16];
buf[0] = b'+';
let len = to_ascii(layout.size(), &mut buf[1..]);
crate::syscall::write(2, buf.as_ptr().cast(), len);
}
let alloc_size = layout.size().next_multiple_of(ALIGN);
unsafe {
if ARENA.base.is_null() || ARENA.offset + alloc_size > ARENA.size {
ARENA = map_chunk(alloc_size);
}
let ptr = ARENA.base.add(ARENA.offset);
ARENA.offset += alloc_size;
ptr
}
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
#[cfg(feature = "print-allocations")]
{
let mut buf = [0u8; 16];
buf[0] = b'+';
let len = to_ascii(layout.size(), &mut buf[1..]);
crate::syscall::write(2, buf.as_ptr().cast(), len);
}
unsafe { self.alloc(layout) }
}
#[allow(unused_variables)]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
#[cfg(feature = "print-allocations")]
{
let mut buf = [0u8; 16];
buf[0] = b'-';
let len = to_ascii(layout.size(), &mut buf[1..]);
crate::syscall::write(2, buf.as_ptr().cast(), len);
}
}
}