diff --git a/src/mm/allocator.rs b/src/mm/allocator.rs index 941fff33b6..ce80e5c3b2 100644 --- a/src/mm/allocator.rs +++ b/src/mm/allocator.rs @@ -6,11 +6,15 @@ use core::alloc::{GlobalAlloc, Layout}; use hermit_sync::RawInterruptTicketMutex; use talc::{ErrOnOom, Span, Talc, Talck}; -pub struct LockedAllocator(Talck); +use crate::mm::bump_allocator::BumpAllocator; + +//pub struct LockedAllocator(Talck); +pub struct LockedAllocator(BumpAllocator); impl LockedAllocator { pub const fn new() -> Self { - Self(Talc::new(ErrOnOom).lock()) + //Self(Talc::new(ErrOnOom).lock()) + Self(BumpAllocator::new()) } #[inline] @@ -22,10 +26,11 @@ impl LockedAllocator { } pub unsafe fn init(&self, heap_bottom: *mut u8, heap_size: usize) { - let arena = Span::from_base_size(heap_bottom, heap_size); - unsafe { - self.0.lock().claim(arena).unwrap(); - } + //let arena = Span::from_base_size(heap_bottom, heap_size); + //unsafe { + //self.0.lock().claim(arena).unwrap(); + //} + self.0.init(heap_bottom, heap_size); } } diff --git a/src/mm/bump_allocator.rs b/src/mm/bump_allocator.rs new file mode 100644 index 0000000000..b2da861b25 --- /dev/null +++ b/src/mm/bump_allocator.rs @@ -0,0 +1,71 @@ +//! A simple bump memory allocator. + +use alloc::alloc::Layout; +use core::alloc::GlobalAlloc; +use core::ptr; +use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; + +use align_address::Align; +use log::{trace, warn}; + +/// A simple bump allocator. +pub(crate) struct BumpAllocator { + mem: AtomicPtr, + size: AtomicUsize, + next: AtomicUsize, + // For stats: + total_waste: AtomicUsize, + waste_cnt: AtomicUsize, +} + +impl BumpAllocator { + pub const fn new() -> Self { + Self { + mem: AtomicPtr::::new(core::ptr::null_mut()), + size: AtomicUsize::new(0), + next: AtomicUsize::new(0), + total_waste: AtomicUsize::new(0), + waste_cnt: AtomicUsize::new(0), + } + } + + pub fn init(&self, mem: *mut u8, size: usize) { + debug!("Initializing bump allocator at {mem:#p} with {size:#x} bytes"); + self.mem.store(mem, Ordering::Relaxed); + self.size.store(size, Ordering::Relaxed); + } +} + +unsafe impl GlobalAlloc for BumpAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + trace!("Bump-allocating {:?}", layout); + let size = layout.size().align_up(layout.align()); + let index = self.next.fetch_add(size, Ordering::Relaxed); + + if index + size <= self.size.load(Ordering::Relaxed) { + unsafe { self.mem.load(Ordering::Relaxed).add(index) } + } else { + warn!("Bump allocator overflow!"); + ptr::null_mut() + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let waste = self.total_waste.fetch_add(layout.size(), Ordering::Relaxed); + let cnt = self.waste_cnt.fetch_add(1, Ordering::Relaxed); + if cnt % (512 * 64) == 511 { + debug!( + "Total bump allocator memory waste: {:#x} Bytes", + waste + layout.size() + ); + } + // This does nothing, since this allocator does not support deallocation. + trace!("Trying to deallocate {:?} at {:p}", layout, ptr); + } +} + +impl Drop for BumpAllocator { + fn drop(&mut self) { + panic!("BumpAllocator should not be dropped") + } +} diff --git a/src/mm/mod.rs b/src/mm/mod.rs index 79241449dc..578c212c06 100644 --- a/src/mm/mod.rs +++ b/src/mm/mod.rs @@ -41,6 +41,7 @@ //! ``` pub(crate) mod allocator; +pub(crate) mod bump_allocator; pub(crate) mod device_alloc; pub(crate) mod physicalmem; pub(crate) mod virtualmem;