Skip to content

Instantly share code, notes, and snippets.

@jamesmunns
Last active June 20, 2022 01:06
Show Gist options
  • Save jamesmunns/2ba8fbbed3ecaee8ecaced0d66f37e37 to your computer and use it in GitHub Desktop.
Save jamesmunns/2ba8fbbed3ecaee8ecaced0d66f37e37 to your computer and use it in GitHub Desktop.
/// 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