mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-21 15:10:44 +00:00
more memory allocation stuff
This commit is contained in:
@@ -5,12 +5,14 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use spin;
|
||||
|
||||
const BLOCK_SIZE: usize = 16*1024;
|
||||
use crate::allocator::r#static::StaticAllocator;
|
||||
|
||||
const BLOCK_SIZE: usize = 16 * 1024;
|
||||
|
||||
const INVALID_BLOCK: u64 = u64::MAX;
|
||||
|
||||
pub(crate) struct BlockAllocator {
|
||||
blocks_ptr: *mut MaybeUninit<u8>,
|
||||
pub(crate) struct BlockAllocator<'t> {
|
||||
blocks_ptr: &'t [MaybeUninit<u8>],
|
||||
num_blocks: u64,
|
||||
num_initialized: AtomicU64,
|
||||
|
||||
@@ -28,23 +30,19 @@ struct FreeListBlockInner {
|
||||
free_blocks: [u64; 100], // FIXME: fill the rest of the block
|
||||
}
|
||||
|
||||
impl<'t> BlockAllocator<'t> {
|
||||
pub(crate) fn new(area: &'t mut [MaybeUninit<u8>]) -> Self {
|
||||
let mut alloc = StaticAllocator::new(area);
|
||||
|
||||
impl BlockAllocator {
|
||||
pub(crate) fn new(ptr: *mut MaybeUninit<u8>, size: usize) -> Self {
|
||||
let mut p = ptr;
|
||||
// Use all the space for the blocks
|
||||
let padding = p.align_offset(BLOCK_SIZE);
|
||||
p = unsafe { p.byte_add(padding) };
|
||||
let blocks_ptr = p;
|
||||
alloc.align(BLOCK_SIZE);
|
||||
|
||||
let used = unsafe { p.byte_offset_from(ptr) as usize };
|
||||
assert!(used <= size);
|
||||
let blocks_size = size - used;
|
||||
let remain = alloc.remaining();
|
||||
|
||||
let num_blocks = (blocks_size / BLOCK_SIZE) as u64;
|
||||
let num_blocks = (remain.len() / BLOCK_SIZE) as u64;
|
||||
|
||||
BlockAllocator {
|
||||
blocks_ptr,
|
||||
blocks_ptr: remain,
|
||||
num_blocks,
|
||||
num_initialized: AtomicU64::new(0),
|
||||
freelist_head: spin::Mutex::new(INVALID_BLOCK),
|
||||
@@ -60,7 +58,13 @@ impl BlockAllocator {
|
||||
|
||||
fn get_block_ptr(&self, blkno: u64) -> *mut u8 {
|
||||
assert!(blkno < self.num_blocks);
|
||||
unsafe { self.blocks_ptr.byte_offset(blkno as isize * BLOCK_SIZE as isize) }.cast()
|
||||
unsafe {
|
||||
self.blocks_ptr
|
||||
.as_ptr()
|
||||
.byte_offset(blkno as isize * BLOCK_SIZE as isize)
|
||||
}
|
||||
.cast_mut()
|
||||
.cast()
|
||||
}
|
||||
|
||||
pub(crate) fn alloc_block(&self) -> *mut u8 {
|
||||
@@ -95,14 +99,19 @@ impl BlockAllocator {
|
||||
// If there are some blocks left that we've never used, pick next such block
|
||||
let mut next_uninitialized = self.num_initialized.load(Ordering::Relaxed);
|
||||
while next_uninitialized < self.num_blocks {
|
||||
match self.num_initialized.compare_exchange(next_uninitialized, next_uninitialized + 1, Ordering::Relaxed, Ordering::Relaxed) {
|
||||
match self.num_initialized.compare_exchange(
|
||||
next_uninitialized,
|
||||
next_uninitialized + 1,
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
) {
|
||||
Ok(_) => {
|
||||
return next_uninitialized;
|
||||
},
|
||||
}
|
||||
Err(old) => {
|
||||
next_uninitialized = old;
|
||||
continue;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
56
libs/neonart/src/allocator/multislab.rs
Normal file
56
libs/neonart/src/allocator/multislab.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use std::alloc::Layout;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use crate::allocator::block::BlockAllocator;
|
||||
use crate::allocator::slab::SlabDesc;
|
||||
use crate::allocator::r#static::StaticAllocator;
|
||||
|
||||
pub struct MultiSlabAllocator<'t, const N: usize> {
|
||||
pub(crate) block_allocator: BlockAllocator<'t>,
|
||||
|
||||
pub(crate) slab_descs: [SlabDesc; N],
|
||||
}
|
||||
|
||||
unsafe impl<'t, const N: usize> Sync for MultiSlabAllocator<'t, N> {}
|
||||
unsafe impl<'t, const N: usize> Send for MultiSlabAllocator<'t, N> {}
|
||||
|
||||
impl<'t, const N: usize> MultiSlabAllocator<'t, N> {
|
||||
pub(crate) fn new(
|
||||
area: &'t mut [MaybeUninit<u8>],
|
||||
layouts: &[Layout; N],
|
||||
) -> &'t mut MultiSlabAllocator<'t, N> {
|
||||
// Set up the MultiSlabAllocator struct in the area first
|
||||
let mut allocator = StaticAllocator::new(area);
|
||||
|
||||
let this = allocator.alloc_uninit();
|
||||
|
||||
let block_allocator = BlockAllocator::new(allocator.remaining());
|
||||
|
||||
let this = this.write(MultiSlabAllocator {
|
||||
block_allocator,
|
||||
|
||||
slab_descs: std::array::from_fn(|i| SlabDesc::new(&layouts[i])),
|
||||
});
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
pub(crate) fn alloc_fit(&self, layout: Layout) -> *mut u8 {
|
||||
for i in 0..self.slab_descs.len() {
|
||||
if self.slab_descs[i].layout.align() >= layout.align()
|
||||
&& self.slab_descs[i].layout.size() >= layout.size()
|
||||
{
|
||||
return self.alloc_slab(i);
|
||||
}
|
||||
}
|
||||
panic!("no suitable slab found for allocation");
|
||||
}
|
||||
|
||||
pub(crate) fn alloc_slab(&self, slab_idx: usize) -> *mut u8 {
|
||||
self.slab_descs[slab_idx].alloc_chunk(&self.block_allocator)
|
||||
}
|
||||
|
||||
pub(crate) fn dealloc_slab(&self, slab_idx: usize, ptr: *mut u8) {
|
||||
self.slab_descs[slab_idx].dealloc_chunk(ptr, &self.block_allocator)
|
||||
}
|
||||
}
|
||||
57
libs/neonart/src/allocator/static.rs
Normal file
57
libs/neonart/src/allocator/static.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
pub struct StaticAllocator<'t> {
|
||||
area: &'t mut [MaybeUninit<u8>],
|
||||
}
|
||||
|
||||
impl<'t> StaticAllocator<'t> {
|
||||
pub fn new(_area: &'t mut [MaybeUninit<u8>]) -> StaticAllocator<'t> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn alloc<T>(&mut self, _init: T) -> &'t T {
|
||||
todo!()
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn alloc_uninit<T>(&mut self) -> &'t mut MaybeUninit<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn remaining(self) -> &'t mut [MaybeUninit<u8>] {
|
||||
self.area
|
||||
}
|
||||
|
||||
pub fn align(&mut self, _alignment: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
pub fn static_alloc<'a, T: Sized>(&'a self, value: T) -> AllocatedBox<'a, T> {
|
||||
let sz = std::mem::size_of::<T>();
|
||||
|
||||
// pad all allocations to MAXALIGN boundaries
|
||||
assert!(std::mem::align_of::<T>() <= MAXALIGN);
|
||||
let sz = sz.next_multiple_of(MAXALIGN);
|
||||
|
||||
let offset = self.allocated.fetch_add(sz, Ordering::Relaxed);
|
||||
|
||||
if offset + sz > self.size {
|
||||
panic!("out of memory");
|
||||
}
|
||||
|
||||
let inner = unsafe {
|
||||
let inner = self.area.offset(offset as isize).cast::<T>();
|
||||
*inner = value;
|
||||
NonNull::new_unchecked(inner)
|
||||
};
|
||||
|
||||
AllocatedBox {
|
||||
inner,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user