#![allow(dead_code, deprecated, unused_variables, unused_mut)] use std::alloc::{GlobalAlloc, Layout}; use std::cell::UnsafeCell; use std::ptr::null_mut; use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; const ARENA_SIZE: usize = 128 * 1024; const MAX_SUPPORTED_ALIGN: usize = 4096; #[repr(C, align(4096))] struct SimpleAllocator { arena: UnsafeCell<[u8; ARENA_SIZE]>, remaining: AtomicUsize, } #[global_allocator] static ALLOCATOR: SimpleAllocator = SimpleAllocator { arena: UnsafeCell::new([0x55; ARENA_SIZE]), remaining: AtomicUsize::new(ARENA_SIZE), }; unsafe impl Sync for SimpleAllocator {} unsafe impl GlobalAlloc for SimpleAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { let size = layout.size(); let align = layout.align(); let align_mask_to_round_down = !(align - 1); if align > MAX_SUPPORTED_ALIGN { return null_mut(); } let mut allocated = 0; if self .remaining .fetch_update( Relaxed, Relaxed, |mut remaining| { if size > remaining { return None; } remaining -= size; remaining &= align_mask_to_round_down; allocated = remaining; Some(remaining) }, ) .is_err() { return null_mut(); } unsafe { self.arena.get().cast::().add(allocated) } } unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} } fn main() { let _s = format!("allocating a string!"); let currently = ALLOCATOR.remaining.load(Relaxed); println!("allocated so far: {}", ARENA_SIZE - currently); }