Skip to content

Commit be4beb7

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

File tree

4 files changed

+45
-27
lines changed

4 files changed

+45
-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: 20 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,39 @@ impl Heap {
4141
///
4242
/// # Safety
4343
///
44-
/// Obey these or Bad Stuff will happen.
44+
/// Please ensure that `start_addr`` points to valid memory and that `size`` is correct.
4545
///
46-
/// - This function must be called exactly ONCE.
47-
/// - `size > 0`
46+
/// # Panics
47+
///
48+
/// This function will panic if either of the following are true:
49+
///
50+
/// - this function is called more than ONCE.
51+
/// - `size == 0`.
4852
pub unsafe fn init(&self, start_addr: usize, size: usize) {
53+
assert!(size > 0);
4954
critical_section::with(|cs| {
50-
self.heap
51-
.borrow(cs)
52-
.borrow_mut()
53-
.init(start_addr as *mut u8, size);
55+
let mut heap = self.heap.borrow_ref_mut(cs);
56+
assert!(!heap.1);
57+
heap.1 = true;
58+
heap.0.init(start_addr as *mut u8, size);
5459
});
5560
}
5661

5762
/// Returns an estimate of the amount of bytes in use.
5863
pub fn used(&self) -> usize {
59-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().used())
64+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.used())
6065
}
6166

6267
/// Returns an estimate of the amount of bytes available.
6368
pub fn free(&self) -> usize {
64-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().free())
69+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.free())
6570
}
6671

6772
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
6873
critical_section::with(|cs| {
6974
self.heap
70-
.borrow(cs)
71-
.borrow_mut()
75+
.borrow_ref_mut(cs)
76+
.0
7277
.allocate_first_fit(layout)
7378
.ok()
7479
})
@@ -77,8 +82,8 @@ impl Heap {
7782
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
7883
critical_section::with(|cs| {
7984
self.heap
80-
.borrow(cs)
81-
.borrow_mut()
85+
.borrow_ref_mut(cs)
86+
.0
8287
.deallocate(NonNull::new_unchecked(ptr), layout)
8388
});
8489
}

src/tlsf.rs

Lines changed: 17 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,34 @@ impl Heap {
4444
///
4545
/// # Safety
4646
///
47-
/// Obey these or Bad Stuff will happen.
47+
/// Please ensure that `start_addr`` points to valid memory and that `size`` is correct.
4848
///
49-
/// - This function must be called exactly ONCE.
50-
/// - `size > 0`
49+
/// # Panics
50+
///
51+
/// This function will panic if either of the following are true:
52+
///
53+
/// - this function is called more than ONCE.
54+
/// - `size == 0`.
5155
pub unsafe fn init(&self, start_addr: usize, size: usize) {
56+
assert!(size > 0);
5257
critical_section::with(|cs| {
58+
let mut heap = self.heap.borrow_ref_mut(cs);
59+
assert!(!heap.1);
60+
heap.1 = true;
5361
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());
62+
heap.0.insert_free_block_ptr(block.into());
5863
});
5964
}
6065

6166
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
62-
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().allocate(layout))
67+
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).0.allocate(layout))
6368
}
6469

6570
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
6671
critical_section::with(|cs| {
6772
self.heap
68-
.borrow(cs)
69-
.borrow_mut()
73+
.borrow_ref_mut(cs)
74+
.0
7075
.deallocate(NonNull::new_unchecked(ptr), layout.align())
7176
})
7277
}

0 commit comments

Comments
 (0)