Skip to content

Commit c81ef5c

Browse files
committed
[#996] Refactor Bumpallocator
Use NonNull<u8> for the pointer to the memory on construction and add a size parameter. Removed the atomic primitives.
1 parent 81bc5f3 commit c81ef5c

File tree

2 files changed

+51
-24
lines changed

2 files changed

+51
-24
lines changed

iceoryx2-bb/elementary/src/bump_allocator.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,26 @@
1010
//
1111
// SPDX-License-Identifier: Apache-2.0 OR MIT
1212

13+
use core::ptr::NonNull;
14+
use iceoryx2_bb_concurrency::cell::RefCell;
15+
1316
use crate::math::align;
14-
use iceoryx2_bb_concurrency::atomic::AtomicUsize;
15-
use iceoryx2_bb_concurrency::atomic::Ordering;
1617
use iceoryx2_bb_elementary_traits::allocator::{AllocationError, BaseAllocator};
1718

1819
/// A minimalistic [`BumpAllocator`].
1920
pub struct BumpAllocator {
20-
start: *mut u8,
21-
pos: AtomicUsize,
21+
start: NonNull<u8>,
22+
next_free_memory: RefCell<u64>,
23+
start_size: usize,
2224
}
2325

2426
impl BumpAllocator {
2527
/// Creates a new [`BumpAllocator`] that manages the memory starting at `start`.
26-
pub fn new(start: *mut u8) -> Self {
28+
pub fn new(start: NonNull<u8>, size: usize) -> Self {
2729
Self {
2830
start,
29-
pos: AtomicUsize::new(start as usize),
31+
next_free_memory: RefCell::<u64>::new(start.as_ptr().cast::<u64>() as u64),
32+
start_size: size,
3033
}
3134
}
3235
}
@@ -36,20 +39,29 @@ impl BaseAllocator for BumpAllocator {
3639
&self,
3740
layout: core::alloc::Layout,
3841
) -> Result<core::ptr::NonNull<[u8]>, AllocationError> {
39-
let mem = align(self.pos.load(Ordering::Relaxed), layout.align());
40-
self.pos.store(mem + layout.size(), Ordering::Relaxed);
42+
let mem = align(*self.next_free_memory.borrow() as usize, layout.align()) as u64;
43+
let allocated_memory_size =
44+
*self.next_free_memory.borrow() as usize - self.start.as_ptr() as usize;
45+
46+
if allocated_memory_size + layout.size() > self.start_size {
47+
return Err(AllocationError::SizeTooLarge);
48+
}
49+
50+
self.next_free_memory.replace(mem + layout.size() as u64);
4151

4252
unsafe {
4353
Ok(core::ptr::NonNull::new_unchecked(
4454
core::ptr::slice_from_raw_parts_mut(
45-
self.start.add(mem - self.start as usize),
55+
self.start
56+
.add(mem as usize - self.start.as_ptr() as usize)
57+
.as_ptr(),
4658
layout.size(),
4759
),
4860
))
4961
}
5062
}
5163

5264
unsafe fn deallocate(&self, _ptr: core::ptr::NonNull<u8>, _layout: core::alloc::Layout) {
53-
self.pos.store(self.start as usize, Ordering::Relaxed);
65+
self.next_free_memory.replace(self.start.as_ptr() as u64);
5466
}
5567
}

iceoryx2-bb/elementary/tests/bump_allocator_tests.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,45 +15,59 @@ use core::{alloc::Layout, ptr::NonNull};
1515
use iceoryx2_bb_elementary::{bump_allocator::*, math::align};
1616
use iceoryx2_bb_elementary_traits::allocator::BaseAllocator;
1717
use iceoryx2_bb_testing::assert_that;
18+
use std::ptr;
1819

1920
#[test]
2021
fn start_position_is_correctly_used() {
2122
let mut memory = [0u8; 8192];
22-
let start_position: *mut u8 = memory.as_mut_ptr();
23+
let start_position: Option<core::ptr::NonNull<u8>> =
24+
core::ptr::NonNull::<u8>::new(memory.as_mut_ptr());
2325
const MEM_SIZE: usize = 91;
2426
const MEM_ALIGN: usize = 1;
25-
let sut = BumpAllocator::new(start_position);
27+
let sut = BumpAllocator::new(start_position.unwrap(), core::mem::size_of_val(&memory));
2628

2729
let memory = sut
2830
.allocate(Layout::from_size_align(MEM_SIZE, MEM_ALIGN).unwrap())
2931
.unwrap();
3032

31-
assert_that!(unsafe { memory.as_ref() }.as_ptr() as usize, eq start_position as usize);
33+
assert_that!(unsafe { memory.as_ref() }.as_ptr() as usize, eq start_position.unwrap().as_ptr() as usize);
3234
assert_that!(unsafe { memory.as_ref() }.len(), eq MEM_SIZE);
3335
}
3436

37+
#[test]
38+
#[should_panic]
39+
fn start_position_is_null() {
40+
let null_ptr: *const u8 = ptr::null();
41+
let start_position: core::ptr::NonNull<u8> =
42+
core::ptr::NonNull::<u8>::new(null_ptr.cast_mut()).unwrap();
43+
44+
let _sut = BumpAllocator::new(start_position, 0);
45+
}
46+
3547
#[test]
3648
fn allocated_memory_is_correctly_aligned() {
37-
let mut memory = [0u8; 8192];
38-
let start_position: *mut u8 = unsafe { memory.as_mut_ptr().add(1) };
49+
let memory = [0u8; 8192];
50+
let start_position: core::ptr::NonNull<u8> =
51+
unsafe { core::ptr::NonNull::<u8>::new(memory.as_ptr().cast_mut().add(1)).unwrap() };
3952
const MEM_SIZE: usize = 128;
4053
const MEM_ALIGN: usize = 64;
41-
let sut = BumpAllocator::new(start_position);
54+
let sut = BumpAllocator::new(start_position, core::mem::size_of_val(&memory));
4255

4356
let memory = sut
4457
.allocate(Layout::from_size_align(MEM_SIZE, MEM_ALIGN).unwrap())
4558
.unwrap();
4659

47-
assert_that!(unsafe { memory.as_ref() }.as_ptr() as usize, eq align(start_position as usize, MEM_ALIGN));
60+
assert_that!(unsafe { memory.as_ref() }.as_ptr() as usize, eq align(start_position.as_ptr() as usize, MEM_ALIGN));
4861
assert_that!(unsafe { memory.as_ref() }.len(), eq MEM_SIZE);
4962
}
5063

5164
#[test]
5265
fn allocating_many_aligned_chunks_work() {
53-
let mut memory = [0u8; 8192];
54-
let start_position: *mut u8 = unsafe { memory.as_mut_ptr().add(1) };
66+
let memory = [0u8; 8192];
67+
let start_position: core::ptr::NonNull<u8> =
68+
unsafe { core::ptr::NonNull::<u8>::new(memory.as_ptr().cast_mut().add(1)).unwrap() };
5569
const ITERATIONS: u32 = 5;
56-
let sut = BumpAllocator::new(start_position);
70+
let sut = BumpAllocator::new(start_position, core::mem::size_of_val(&memory));
5771

5872
let mut last_size = 0;
5973
let mut last_position = 0;
@@ -76,11 +90,12 @@ fn allocating_many_aligned_chunks_work() {
7690

7791
#[test]
7892
fn deallocating_releases_everything() {
79-
let mut memory = [0u8; 8192];
80-
let start_position: *mut u8 = unsafe { memory.as_mut_ptr().add(3) };
93+
let memory = [0u8; 8192];
94+
let start_position: core::ptr::NonNull<u8> =
95+
unsafe { core::ptr::NonNull::<u8>::new(memory.as_ptr().cast_mut().add(3)).unwrap() };
8196
const MEM_SIZE: usize = 128;
8297
const MEM_ALIGN: usize = 1;
83-
let sut = BumpAllocator::new(start_position);
98+
let sut = BumpAllocator::new(start_position, core::mem::size_of_val(&memory));
8499

85100
let layout = Layout::from_size_align(MEM_SIZE, MEM_ALIGN).unwrap();
86101
let mut memory = sut.allocate(layout).unwrap();
@@ -96,6 +111,6 @@ fn deallocating_releases_everything() {
96111
.allocate(Layout::from_size_align(MEM_SIZE, MEM_ALIGN).unwrap())
97112
.unwrap();
98113

99-
assert_that!(unsafe { memory.as_ref() }.as_ptr() as usize, eq start_position as usize);
114+
assert_that!(unsafe { memory.as_ref() }.as_ptr() as usize, eq start_position.as_ptr() as usize);
100115
assert_that!(unsafe { memory.as_ref() }.len(), eq MEM_SIZE);
101116
}

0 commit comments

Comments
 (0)