Skip to content

Commit b3afee2

Browse files
committed
Add a flag to prevent duplicate initialization
1 parent eb87f1a commit b3afee2

File tree

4 files changed

+39
-23
lines changed

4 files changed

+39
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- Added a `init` macro to make initialization easier.
13+
- Added a flag to prevent duplicate initialization
1314

1415
## [v0.6.0] - 2024-09-01
1516

src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ pub use tlsf::Heap as TlsfHeap;
3030
/// It internally calls `Heap::init(...)` on the heap,
3131
/// so `Heap::init(...)` should not be called directly if this macro is used.
3232
///
33+
/// # Panics
34+
///
35+
/// This macro will panic if either of the following are true:
36+
///
37+
/// - this function is called more than ONCE.
38+
/// - `size == 0`.
39+
///
3340
/// # Example
3441
///
3542
/// ```rust

src/llff.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use linked_list_allocator::Heap as LLHeap;
77

88
/// A linked list first fit heap.
99
pub struct Heap {
10-
heap: Mutex<RefCell<LLHeap>>,
10+
heap: Mutex<RefCell<(LLHeap, bool)>>,
1111
}
1212

1313
impl Heap {
@@ -17,7 +17,7 @@ impl Heap {
1717
/// [`init`](Self::init) method before using the allocator.
1818
pub const fn empty() -> Heap {
1919
Heap {
20-
heap: Mutex::new(RefCell::new(LLHeap::empty())),
20+
heap: Mutex::new(RefCell::new((LLHeap::empty(), false))),
2121
}
2222
}
2323

@@ -41,34 +41,38 @@ impl Heap {
4141
///
4242
/// # Safety
4343
///
44-
/// Obey these or Bad Stuff will happen.
44+
/// This function will panic if either of the following are true:
4545
///
46-
/// - This function must be called exactly ONCE.
47-
/// - `size > 0`
46+
/// - this function is called more than ONCE.
47+
/// - `size == 0`.
4848
pub unsafe fn init(&self, start_addr: usize, size: usize) {
49+
assert!(size > 0);
4950
critical_section::with(|cs| {
51+
assert!(!self.heap.borrow_ref(cs).1);
52+
self.heap.borrow_ref_mut(cs).1 = true;
53+
5054
self.heap
51-
.borrow(cs)
52-
.borrow_mut()
55+
.borrow_ref_mut(cs)
56+
.0
5357
.init(start_addr as *mut u8, size);
5458
});
5559
}
5660

5761
/// Returns an estimate of the amount of bytes in use.
5862
pub fn used(&self) -> usize {
59-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().used())
63+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.used())
6064
}
6165

6266
/// Returns an estimate of the amount of bytes available.
6367
pub fn free(&self) -> usize {
64-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().free())
68+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.free())
6569
}
6670

6771
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
6872
critical_section::with(|cs| {
6973
self.heap
70-
.borrow(cs)
71-
.borrow_mut()
74+
.borrow_ref_mut(cs)
75+
.0
7276
.allocate_first_fit(layout)
7377
.ok()
7478
})
@@ -77,8 +81,8 @@ impl Heap {
7781
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
7882
critical_section::with(|cs| {
7983
self.heap
80-
.borrow(cs)
81-
.borrow_mut()
84+
.borrow_ref_mut(cs)
85+
.0
8286
.deallocate(NonNull::new_unchecked(ptr), layout)
8387
});
8488
}

src/tlsf.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type TlsfHeap = Tlsf<'static, usize, usize, { usize::BITS as usize }, { usize::B
1010

1111
/// A two-Level segregated fit heap.
1212
pub struct Heap {
13-
heap: Mutex<RefCell<TlsfHeap>>,
13+
heap: Mutex<RefCell<(TlsfHeap, bool)>>,
1414
}
1515

1616
impl Heap {
@@ -20,7 +20,7 @@ impl Heap {
2020
/// [`init`](Self::init) method before using the allocator.
2121
pub const fn empty() -> Heap {
2222
Heap {
23-
heap: Mutex::new(RefCell::new(ConstDefault::DEFAULT)),
23+
heap: Mutex::new(RefCell::new((ConstDefault::DEFAULT, false))),
2424
}
2525
}
2626

@@ -44,29 +44,33 @@ impl Heap {
4444
///
4545
/// # Safety
4646
///
47-
/// Obey these or Bad Stuff will happen.
47+
/// This function will panic if either of the following are true:
4848
///
49-
/// - This function must be called exactly ONCE.
50-
/// - `size > 0`
49+
/// - this function is called more than ONCE.
50+
/// - `size == 0`.
5151
pub unsafe fn init(&self, start_addr: usize, size: usize) {
52+
assert!(size > 0);
5253
critical_section::with(|cs| {
54+
assert!(!self.heap.borrow_ref(cs).1);
55+
self.heap.borrow_ref_mut(cs).1 = true;
56+
5357
let block: &[u8] = core::slice::from_raw_parts(start_addr as *const u8, size);
5458
self.heap
55-
.borrow(cs)
56-
.borrow_mut()
59+
.borrow_ref_mut(cs)
60+
.0
5761
.insert_free_block_ptr(block.into());
5862
});
5963
}
6064

6165
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
62-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().allocate(layout))
66+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.allocate(layout))
6367
}
6468

6569
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
6670
critical_section::with(|cs| {
6771
self.heap
68-
.borrow(cs)
69-
.borrow_mut()
72+
.borrow_ref_mut(cs)
73+
.0
7074
.deallocate(NonNull::new_unchecked(ptr), layout.align())
7175
})
7276
}

0 commit comments

Comments
 (0)