Skip to content

Commit b52091a

Browse files
authored
Merge pull request #78 from trueb2/master
Add choice of Two-Level Segregated Fit and Linked List First Fit
2 parents 6875394 + 5114ae5 commit b52091a

File tree

8 files changed

+337
-92
lines changed

8 files changed

+337
-92
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ jobs:
5656
sudo apt update
5757
sudo apt install qemu-system-arm
5858
- run: qemu-system-arm --version
59-
- run: cargo run --target thumbv7m-none-eabi --example integration_test --all-features
59+
- run: cargo run --target thumbv7m-none-eabi --example llff_integration_test --all-features
60+
- run: cargo run --target thumbv7m-none-eabi --example tlsf_integration_test --all-features
6061

6162
clippy:
6263
name: Clippy

Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,20 @@ name = "embedded-alloc"
2424
version = "0.5.1"
2525

2626
[features]
27+
default = ["llff", "tlsf"]
2728
allocator_api = []
2829

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+
2935
[dependencies]
3036
critical-section = "1.0"
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 }
3140

32-
[dependencies.linked_list_allocator]
33-
default-features = false
34-
version = "0.10.5"
3541

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

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Starting with Rust 1.68, this crate can be used as a global allocator on stable
2323
extern crate alloc;
2424

2525
use cortex_m_rt::entry;
26-
use embedded_alloc::Heap;
26+
use embedded_alloc::LlffHeap as Heap;
2727

2828
#[global_allocator]
2929
static HEAP: Heap = Heap::empty();

examples/allocator_api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use alloc::vec::Vec;
88
use core::mem::MaybeUninit;
99
use core::panic::PanicInfo;
1010
use cortex_m_rt::entry;
11-
use embedded_alloc::Heap;
11+
use embedded_alloc::LlffHeap as Heap;
1212

1313
// This is not used, but as of 2023-10-29 allocator_api cannot be used without
1414
// a global heap

examples/global_alloc.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ extern crate alloc;
66
use alloc::vec::Vec;
77
use core::panic::PanicInfo;
88
use cortex_m_rt::entry;
9-
use embedded_alloc::Heap;
9+
// Linked-List First Fit Heap allocator (feature = "llff")
10+
use embedded_alloc::LlffHeap as Heap;
11+
// Two-Level Segregated Fit Heap allocator (feature = "tlsf")
12+
// use embedded_alloc::TlsfHeap as Heap;
1013

1114
#[global_allocator]
1215
static HEAP: Heap = Heap::empty();

examples/integration_test.rs renamed to examples/llff_integration_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//! After toolchain installation this test can be run with:
88
//!
99
//! ```bash
10-
//! cargo +nightly run --target thumbv7m-none-eabi --example integration_test --all-features
10+
//! cargo +nightly run --target thumbv7m-none-eabi --example llff_integration_test --all-features
1111
//! ```
1212
//!
1313
//! [Embedded Rust Book]: https://docs.rust-embedded.org/book/intro/index.html
@@ -23,7 +23,7 @@ use alloc::vec::Vec;
2323
use core::mem::{size_of, MaybeUninit};
2424
use cortex_m_rt::entry;
2525
use cortex_m_semihosting::{debug, hprintln};
26-
use embedded_alloc::Heap;
26+
use embedded_alloc::LlffHeap as Heap;
2727

2828
#[global_allocator]
2929
static HEAP: Heap = Heap::empty();

examples/tlsf_integration_test.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//! This is a very basic smoke test that runs in QEMU
2+
//! Reference the QEMU section of the [Embedded Rust Book] for more information
3+
//!
4+
//! This only tests integration of the allocator on an embedded target.
5+
//! Comprehensive allocator tests are located in the allocator dependency.
6+
//!
7+
//! After toolchain installation this test can be run with:
8+
//!
9+
//! ```bash
10+
//! cargo +nightly run --target thumbv7m-none-eabi --example tlsf_integration_test --all-features
11+
//! ```
12+
//!
13+
//! [Embedded Rust Book]: https://docs.rust-embedded.org/book/intro/index.html
14+
15+
#![feature(allocator_api)]
16+
#![no_main]
17+
#![no_std]
18+
19+
extern crate alloc;
20+
extern crate panic_semihosting;
21+
22+
use alloc::collections::LinkedList;
23+
use core::mem::MaybeUninit;
24+
use cortex_m_rt::entry;
25+
use cortex_m_semihosting::{debug, hprintln};
26+
use embedded_alloc::TlsfHeap as Heap;
27+
28+
#[global_allocator]
29+
static HEAP: Heap = Heap::empty();
30+
const HEAP_SIZE: usize = 30 * 1024;
31+
32+
fn test_global_heap() {
33+
const ELEMS: usize = 250;
34+
35+
let mut allocated = LinkedList::new();
36+
for _ in 0..ELEMS {
37+
allocated.push_back(0);
38+
}
39+
for i in 0..ELEMS {
40+
allocated.push_back(i as i32);
41+
}
42+
43+
assert_eq!(allocated.len(), 2 * ELEMS);
44+
45+
for _ in 0..ELEMS {
46+
allocated.pop_front();
47+
}
48+
49+
for i in 0..ELEMS {
50+
assert_eq!(allocated.pop_front().unwrap(), i as i32);
51+
}
52+
}
53+
54+
fn test_allocator_api() {
55+
// small local heap
56+
const HEAP_SIZE: usize = 256;
57+
let heap_mem: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
58+
let local_heap: Heap = Heap::empty();
59+
unsafe { local_heap.init(heap_mem.as_ptr() as usize, HEAP_SIZE) }
60+
61+
const ELEMS: usize = 2;
62+
63+
let mut allocated = LinkedList::new_in(local_heap);
64+
for _ in 0..ELEMS {
65+
allocated.push_back(0);
66+
}
67+
for i in 0..ELEMS {
68+
allocated.push_back(i as i32);
69+
}
70+
71+
assert_eq!(allocated.len(), 2 * ELEMS);
72+
73+
for _ in 0..ELEMS {
74+
allocated.pop_front();
75+
}
76+
77+
for i in 0..ELEMS {
78+
assert_eq!(allocated.pop_front().unwrap(), i as i32);
79+
}
80+
}
81+
82+
#[entry]
83+
fn main() -> ! {
84+
{
85+
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
86+
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
87+
}
88+
89+
#[allow(clippy::type_complexity)]
90+
let tests: &[(fn() -> (), &'static str)] = &[
91+
(test_global_heap, "test_global_heap"),
92+
(test_allocator_api, "test_allocator_api"),
93+
];
94+
95+
for (test_fn, test_name) in tests {
96+
hprintln!("{}: start", test_name);
97+
test_fn();
98+
hprintln!("{}: pass", test_name);
99+
}
100+
101+
// exit QEMU with a success status
102+
debug::exit(debug::EXIT_SUCCESS);
103+
#[allow(clippy::empty_loop)]
104+
loop {}
105+
}

0 commit comments

Comments
 (0)