-
-
Save jamesmunns/2ba8fbbed3ecaee8ecaced0d66f37e37 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Construct a thread safe async allocator from a pool of memory. | |
/// | |
/// Safety: The pool of memory MUST be valid for the 'static lifetime, e.g. | |
/// obtained by a leaked buffer, a linker section, or some other mechanism. | |
/// Additionally, we must semantically have exclusive access to this region | |
/// of memory: There must be no other live references, or pointers to this | |
/// region that are dereferenced after this call. | |
pub unsafe fn bootstrap(addr: usize, size: usize) -> Result<(&'static Self, HeapGuard), ()> { | |
// First, we go all bump-allocator to emplace ourselves within this region | |
let mut cursor = addr as *mut u8; | |
let end = addr.checked_add(size).ok_or(())?; | |
let mut used = 0; | |
let stub_ptr; | |
let aheap_ptr; | |
// We start with the stub node required for our mpsc queue. | |
{ | |
let stub_layout = Layout::new::<Recycle>(); | |
let stub_offset = cursor.align_offset(stub_layout.align()); | |
let stub_size = stub_layout.size(); | |
used += stub_offset; | |
used += stub_size; | |
if used > size { | |
return Err(()); | |
} | |
cursor = cursor.add(stub_offset); | |
stub_ptr = cursor.cast::<Recycle>(); | |
stub_ptr.write(Recycle { | |
links: Links::new_stub(), | |
node_layout: stub_layout, | |
}); | |
cursor = cursor.add(stub_size); | |
} | |
// Next we allocate ourselves | |
{ | |
let aheap_layout = Layout::new::<Self>(); | |
let aheap_offset = cursor.align_offset(aheap_layout.align()); | |
let aheap_size = aheap_layout.size(); | |
used += aheap_offset; | |
used += aheap_size; | |
if used > size { | |
return Err(()); | |
} | |
cursor = cursor.add(aheap_offset); | |
aheap_ptr = cursor.cast::<Self>(); | |
aheap_ptr.write(Self { | |
freelist: MpscQueue::new_with_static_stub(&*stub_ptr), | |
state: AtomicU8::new(Self::BUSY_LOCKED), | |
heap: UnsafeCell::new(MaybeUninit::uninit()), | |
heap_wait: WaitQueue::new(), | |
inhibit_alloc: AtomicBool::new(false), | |
any_frees: AtomicBool::new(false), | |
}); | |
cursor = cursor.add(aheap_size); | |
} | |
// Everything else is now our allocation space. Initialize the inner | |
// heap allocator. | |
let aheap: &'static Self = &*aheap_ptr; | |
aheap.heap.get().write(MaybeUninit::new(Heap::new( | |
cursor as usize, | |
end - (cursor as usize) | |
))); | |
let iheap = &mut *aheap.heap.get().cast(); | |
let guard = HeapGuard { heap: iheap }; | |
// Well that went great, I think! We'l | |
Ok((aheap, guard)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment