11use crate :: error:: { MemoryError , MemoryErrorKind , MemoryResult } ;
22use beskar_core:: arch:: paging:: { M4KiB , MemSize as _} ;
33use core:: { num:: NonZeroU64 , ptr:: NonNull } ;
4+ use heaperion:: { DefaultGrowableHeap , HybridAllocator } ;
45use hyperdrive:: locks:: mcs:: MUMcsLock ;
56
6- static ALLOCATOR : MUMcsLock < heaperion:: Heap > = MUMcsLock :: uninit ( ) ;
7-
8- struct Heap ;
7+ static ALLOCATOR : MUMcsLock < DefaultGrowableHeap < Mmap , 4 > > = MUMcsLock :: uninit ( ) ;
98
109#[ global_allocator]
1110static HEAP : Heap = Heap ;
1211
13- pub ( crate ) const HEAP_SIZE : u64 = 20 * 1024 * 1024 ; // 20 MiB
14- beskar_core:: static_assert!( HEAP_SIZE . is_multiple_of( M4KiB :: SIZE ) ) ;
12+ const HEAP_START_SIZE : u64 = 16 * 1024 * 1024 ; // 16 MiB
13+ beskar_core:: static_assert!( HEAP_START_SIZE . is_multiple_of( M4KiB :: SIZE ) ) ;
14+
15+ struct Heap ;
1516
1617unsafe impl core:: alloc:: GlobalAlloc for Heap {
1718 unsafe fn alloc ( & self , layout : core:: alloc:: Layout ) -> * mut u8 {
@@ -30,8 +31,15 @@ unsafe impl core::alloc::GlobalAlloc for Heap {
3031
3132#[ inline]
3233/// Initialize the heap allocator
33- pub ( crate ) unsafe fn init_heap ( start : * mut u8 , size : usize ) {
34- ALLOCATOR . init ( unsafe { heaperion:: Heap :: new ( start, size) } . unwrap ( ) ) ;
34+ pub ( super ) fn init_heap ( ) {
35+ let size = HEAP_START_SIZE ;
36+ let start = mmap ( size, None , MemoryProtection :: ReadWrite ) . unwrap ( ) ;
37+
38+ // SAFETY: `start` and `size` come from a successful call to `mmap` and are not used after this point.
39+ let heap =
40+ unsafe { HybridAllocator :: new ( start. as_ptr ( ) , usize:: try_from ( size) . unwrap ( ) ) } . unwrap ( ) ;
41+ let growable = DefaultGrowableHeap :: new ( heap, Mmap ) ;
42+ ALLOCATOR . init ( growable) ;
3543}
3644
3745/// Map memory into the address space
@@ -76,6 +84,77 @@ pub fn mprotect(ptr: *mut u8, size: u64, flags: MemoryProtection) -> bool {
7684 res. is_success ( )
7785}
7886
87+ pub struct MmapReadWrite {
88+ ptr : NonNull < u8 > ,
89+ size : u64 ,
90+ }
91+
92+ impl MmapReadWrite {
93+ #[ inline]
94+ /// Create a new read-write memory mapping of the given size.
95+ ///
96+ /// # Errors
97+ ///
98+ /// Returns an error if the memory cannot be mapped.
99+ pub fn new ( size : u64 ) -> MemoryResult < Self > {
100+ let ptr = mmap ( size, None , MemoryProtection :: ReadWrite ) ?;
101+ Ok ( Self { ptr, size } )
102+ }
103+
104+ #[ must_use]
105+ #[ inline]
106+ pub const fn size ( & self ) -> u64 {
107+ self . size
108+ }
109+
110+ #[ must_use]
111+ #[ inline]
112+ pub const fn as_ptr ( & self ) -> * mut u8 {
113+ self . ptr . as_ptr ( )
114+ }
115+
116+ #[ must_use]
117+ #[ inline]
118+ #[ expect( clippy:: missing_panics_doc, reason = "Never panics" ) ]
119+ pub fn as_slice ( & self ) -> & [ u8 ] {
120+ let data = self . as_ptr ( ) ;
121+ let len = usize:: try_from ( self . size ) . unwrap ( ) ;
122+ unsafe { core:: slice:: from_raw_parts ( data. cast :: < u8 > ( ) , len) }
123+ }
124+
125+ #[ must_use]
126+ #[ inline]
127+ #[ expect( clippy:: missing_panics_doc, reason = "Never panics" ) ]
128+ pub fn as_mut_slice ( & mut self ) -> & mut [ u8 ] {
129+ let data = self . as_ptr ( ) ;
130+ let len = usize:: try_from ( self . size ) . unwrap ( ) ;
131+ unsafe { core:: slice:: from_raw_parts_mut ( data. cast :: < u8 > ( ) , len) }
132+ }
133+ }
134+
135+ impl Drop for MmapReadWrite {
136+ fn drop ( & mut self ) {
137+ // Safety: `ptr` and `size` come from a previous, successful call to `mmap`
138+ // and are not used after this point.
139+ unsafe {
140+ munmap ( self . ptr . as_ptr ( ) , self . size ) ;
141+ }
142+ }
143+ }
144+
145+ struct Mmap ;
146+ unsafe impl heaperion:: MemorySource for Mmap {
147+ fn request ( & mut self , min_size : usize ) -> Option < ( * mut u8 , usize ) > {
148+ let ptr = mmap (
149+ u64:: try_from ( min_size) . unwrap ( ) ,
150+ None ,
151+ MemoryProtection :: ReadWrite ,
152+ )
153+ . ok ( ) ?;
154+ Some ( ( ptr. as_ptr ( ) , min_size) )
155+ }
156+ }
157+
79158#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
80159#[ repr( u64 ) ]
81160pub enum MemoryProtection {
0 commit comments