Skip to content

Commit 3ff3036

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

File tree

4 files changed

+37
-27
lines changed

4 files changed

+37
-27
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: 16 additions & 15 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,35 @@ 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| {
50-
self.heap
51-
.borrow(cs)
52-
.borrow_mut()
53-
.init(start_addr as *mut u8, size);
51+
let mut heap = self.heap.borrow_ref_mut(cs);
52+
assert!(!heap.1);
53+
heap.1 = true;
54+
heap.0.init(start_addr as *mut u8, size);
5455
});
5556
}
5657

5758
/// Returns an estimate of the amount of bytes in use.
5859
pub fn used(&self) -> usize {
59-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().used())
60+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.used())
6061
}
6162

6263
/// Returns an estimate of the amount of bytes available.
6364
pub fn free(&self) -> usize {
64-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().free())
65+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.free())
6566
}
6667

6768
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
6869
critical_section::with(|cs| {
6970
self.heap
70-
.borrow(cs)
71-
.borrow_mut()
71+
.borrow_ref_mut(cs)
72+
.0
7273
.allocate_first_fit(layout)
7374
.ok()
7475
})
@@ -77,8 +78,8 @@ impl Heap {
7778
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
7879
critical_section::with(|cs| {
7980
self.heap
80-
.borrow(cs)
81-
.borrow_mut()
81+
.borrow_ref_mut(cs)
82+
.0
8283
.deallocate(NonNull::new_unchecked(ptr), layout)
8384
});
8485
}

src/tlsf.rs

Lines changed: 13 additions & 12 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,30 @@ 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+
let mut heap = self.heap.borrow_ref_mut(cs);
55+
assert!(!heap.1);
56+
heap.1 = true;
5357
let block: &[u8] = core::slice::from_raw_parts(start_addr as *const u8, size);
54-
self.heap
55-
.borrow(cs)
56-
.borrow_mut()
57-
.insert_free_block_ptr(block.into());
58+
heap.0.insert_free_block_ptr(block.into());
5859
});
5960
}
6061

6162
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
62-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().allocate(layout))
63+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.allocate(layout))
6364
}
6465

6566
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
6667
critical_section::with(|cs| {
6768
self.heap
68-
.borrow(cs)
69-
.borrow_mut()
69+
.borrow_ref_mut(cs)
70+
.0
7071
.deallocate(NonNull::new_unchecked(ptr), layout.align())
7172
})
7273
}

0 commit comments

Comments
 (0)