Skip to content

Commit 91c31ae

Browse files
committed
Add choice of Two-Level Segregate Fit and Linked List First Fit
1 parent 5654f2a commit 91c31ae

File tree

2 files changed

+79
-18
lines changed

2 files changed

+79
-18
lines changed

Cargo.toml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@ license = "MIT OR Apache-2.0"
2323
name = "embedded-alloc"
2424
version = "0.5.0"
2525

26+
[features]
27+
# Choose exactly 1 allocator
28+
default = []
29+
30+
# Use the Two-Level Segregated Fit allocator
31+
tlsf = ["rlsf", "const-default"]
32+
# Use the LinkedList first-fit allocator
33+
llff = ["linked_list_allocator"]
34+
2635
[dependencies]
2736
critical-section = "1.0"
28-
29-
[dependencies.linked_list_allocator]
30-
default-features = false
31-
version = "0.10.5"
37+
linked_list_allocator = { version = "0.10.5", default-features = false, optional = true }
38+
rlsf = { version = "0.2.1", default-features = false, optional = true }
39+
const-default = { version = "1.0.0", default-features = false, optional = true }
3240

3341
[dev-dependencies]
3442
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }

src/lib.rs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,27 @@ use core::alloc::{GlobalAlloc, Layout};
55
use core::cell::RefCell;
66
use core::ptr::{self, NonNull};
77

8+
#[cfg(feature = "tlsf")]
9+
use const_default::ConstDefault;
810
use critical_section::Mutex;
11+
12+
// Exactly one of these features must be enabled: "llff" or "tlsf"
13+
#[cfg(all(feature = "tlsf", feature = "llff"))]
14+
compile_error!("You can't enable both 'tlsf' and 'llff' features simultaneously. Choose one allocator.");
15+
16+
#[cfg(feature = "llff")]
917
use linked_list_allocator::Heap as LLHeap;
18+
#[cfg(feature = "tlsf")]
19+
use rlsf::Tlsf;
20+
21+
#[cfg(feature = "tlsf")]
22+
type TlsfHeap = Tlsf<'static, usize, usize, { usize::BITS as usize }, { usize::BITS as usize }>;
1023

1124
pub struct Heap {
25+
#[cfg(feature = "llff")]
1226
heap: Mutex<RefCell<LLHeap>>,
27+
#[cfg(feature = "tlsf")]
28+
heap: Mutex<RefCell<TlsfHeap>>,
1329
}
1430

1531
impl Heap {
@@ -19,7 +35,10 @@ impl Heap {
1935
/// [`init`](Self::init) method before using the allocator.
2036
pub const fn empty() -> Heap {
2137
Heap {
38+
#[cfg(feature = "llff")]
2239
heap: Mutex::new(RefCell::new(LLHeap::empty())),
40+
#[cfg(feature = "tlsf")]
41+
heap: Mutex::new(RefCell::new(ConstDefault::DEFAULT)),
2342
}
2443
}
2544

@@ -49,19 +68,32 @@ impl Heap {
4968
/// - `size > 0`
5069
pub unsafe fn init(&self, start_addr: usize, size: usize) {
5170
critical_section::with(|cs| {
52-
self.heap
53-
.borrow(cs)
54-
.borrow_mut()
55-
.init(start_addr as *mut u8, size);
71+
#[cfg(feature = "llff")]
72+
{
73+
self.heap
74+
.borrow(cs)
75+
.borrow_mut()
76+
.init(start_addr as *mut u8, size);
77+
}
78+
#[cfg(feature = "tlsf")]
79+
{
80+
let block: &[u8] = core::slice::from_raw_parts(start_addr as *const u8, size);
81+
self.heap
82+
.borrow(cs)
83+
.borrow_mut()
84+
.insert_free_block_ptr(block.into());
85+
}
5686
});
5787
}
5888

5989
/// Returns an estimate of the amount of bytes in use.
90+
#[cfg(feature = "llff")]
6091
pub fn used(&self) -> usize {
6192
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().used())
6293
}
6394

6495
/// Returns an estimate of the amount of bytes available.
96+
#[cfg(feature = "llff")]
6597
pub fn free(&self) -> usize {
6698
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().free())
6799
}
@@ -70,21 +102,42 @@ impl Heap {
70102
unsafe impl GlobalAlloc for Heap {
71103
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
72104
critical_section::with(|cs| {
73-
self.heap
74-
.borrow(cs)
75-
.borrow_mut()
76-
.allocate_first_fit(layout)
77-
.ok()
78-
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
105+
#[cfg(feature = "llff")]
106+
{
107+
self.heap
108+
.borrow(cs)
109+
.borrow_mut()
110+
.allocate_first_fit(layout)
111+
.ok()
112+
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
113+
}
114+
#[cfg(feature = "tlsf")]
115+
{
116+
self.heap
117+
.borrow(cs)
118+
.borrow_mut()
119+
.allocate(layout)
120+
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
121+
}
79122
})
80123
}
81124

82125
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
83126
critical_section::with(|cs| {
84-
self.heap
85-
.borrow(cs)
86-
.borrow_mut()
87-
.deallocate(NonNull::new_unchecked(ptr), layout)
127+
#[cfg(feature = "llff")]
128+
{
129+
self.heap
130+
.borrow(cs)
131+
.borrow_mut()
132+
.deallocate(NonNull::new_unchecked(ptr), layout)
133+
}
134+
#[cfg(feature = "tlsf")]
135+
{
136+
self.heap
137+
.borrow(cs)
138+
.borrow_mut()
139+
.deallocate(NonNull::new_unchecked(ptr), layout.align())
140+
}
88141
});
89142
}
90143
}

0 commit comments

Comments
 (0)