Skip to content

Commit

Permalink
Merge pull request #78 from trueb2/master
Browse files Browse the repository at this point in the history
Add choice of Two-Level Segregated Fit and Linked List First Fit
  • Loading branch information
newAM committed Dec 14, 2023
2 parents 6875394 + 5114ae5 commit b52091a
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 92 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ jobs:
sudo apt update
sudo apt install qemu-system-arm
- run: qemu-system-arm --version
- run: cargo run --target thumbv7m-none-eabi --example integration_test --all-features
- run: cargo run --target thumbv7m-none-eabi --example llff_integration_test --all-features
- run: cargo run --target thumbv7m-none-eabi --example tlsf_integration_test --all-features

clippy:
name: Clippy
Expand Down
12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ name = "embedded-alloc"
version = "0.5.1"

[features]
default = ["llff", "tlsf"]
allocator_api = []

# Use the Two-Level Segregated Fit allocator
tlsf = ["rlsf", "const-default"]
# Use the LinkedList first-fit allocator
llff = ["linked_list_allocator"]

[dependencies]
critical-section = "1.0"
linked_list_allocator = { version = "0.10.5", default-features = false, optional = true }
rlsf = { version = "0.2.1", default-features = false, optional = true }
const-default = { version = "1.0.0", default-features = false, optional = true }

[dependencies.linked_list_allocator]
default-features = false
version = "0.10.5"

[dev-dependencies]
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Starting with Rust 1.68, this crate can be used as a global allocator on stable
extern crate alloc;

use cortex_m_rt::entry;
use embedded_alloc::Heap;
use embedded_alloc::LlffHeap as Heap;

#[global_allocator]
static HEAP: Heap = Heap::empty();
Expand Down
2 changes: 1 addition & 1 deletion examples/allocator_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use alloc::vec::Vec;
use core::mem::MaybeUninit;
use core::panic::PanicInfo;
use cortex_m_rt::entry;
use embedded_alloc::Heap;
use embedded_alloc::LlffHeap as Heap;

// This is not used, but as of 2023-10-29 allocator_api cannot be used without
// a global heap
Expand Down
5 changes: 4 additions & 1 deletion examples/global_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ extern crate alloc;
use alloc::vec::Vec;
use core::panic::PanicInfo;
use cortex_m_rt::entry;
use embedded_alloc::Heap;
// Linked-List First Fit Heap allocator (feature = "llff")
use embedded_alloc::LlffHeap as Heap;
// Two-Level Segregated Fit Heap allocator (feature = "tlsf")
// use embedded_alloc::TlsfHeap as Heap;

#[global_allocator]
static HEAP: Heap = Heap::empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! After toolchain installation this test can be run with:
//!
//! ```bash
//! cargo +nightly run --target thumbv7m-none-eabi --example integration_test --all-features
//! cargo +nightly run --target thumbv7m-none-eabi --example llff_integration_test --all-features
//! ```
//!
//! [Embedded Rust Book]: https://docs.rust-embedded.org/book/intro/index.html
Expand All @@ -23,7 +23,7 @@ use alloc::vec::Vec;
use core::mem::{size_of, MaybeUninit};
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
use embedded_alloc::Heap;
use embedded_alloc::LlffHeap as Heap;

#[global_allocator]
static HEAP: Heap = Heap::empty();
Expand Down
105 changes: 105 additions & 0 deletions examples/tlsf_integration_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//! This is a very basic smoke test that runs in QEMU
//! Reference the QEMU section of the [Embedded Rust Book] for more information
//!
//! This only tests integration of the allocator on an embedded target.
//! Comprehensive allocator tests are located in the allocator dependency.
//!
//! After toolchain installation this test can be run with:
//!
//! ```bash
//! cargo +nightly run --target thumbv7m-none-eabi --example tlsf_integration_test --all-features
//! ```
//!
//! [Embedded Rust Book]: https://docs.rust-embedded.org/book/intro/index.html

#![feature(allocator_api)]
#![no_main]
#![no_std]

extern crate alloc;
extern crate panic_semihosting;

use alloc::collections::LinkedList;
use core::mem::MaybeUninit;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
use embedded_alloc::TlsfHeap as Heap;

#[global_allocator]
static HEAP: Heap = Heap::empty();
const HEAP_SIZE: usize = 30 * 1024;

fn test_global_heap() {
const ELEMS: usize = 250;

let mut allocated = LinkedList::new();
for _ in 0..ELEMS {
allocated.push_back(0);
}
for i in 0..ELEMS {
allocated.push_back(i as i32);
}

assert_eq!(allocated.len(), 2 * ELEMS);

for _ in 0..ELEMS {
allocated.pop_front();
}

for i in 0..ELEMS {
assert_eq!(allocated.pop_front().unwrap(), i as i32);
}
}

fn test_allocator_api() {
// small local heap
const HEAP_SIZE: usize = 256;
let heap_mem: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
let local_heap: Heap = Heap::empty();
unsafe { local_heap.init(heap_mem.as_ptr() as usize, HEAP_SIZE) }

const ELEMS: usize = 2;

let mut allocated = LinkedList::new_in(local_heap);
for _ in 0..ELEMS {
allocated.push_back(0);
}
for i in 0..ELEMS {
allocated.push_back(i as i32);
}

assert_eq!(allocated.len(), 2 * ELEMS);

for _ in 0..ELEMS {
allocated.pop_front();
}

for i in 0..ELEMS {
assert_eq!(allocated.pop_front().unwrap(), i as i32);
}
}

#[entry]
fn main() -> ! {
{
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
}

#[allow(clippy::type_complexity)]
let tests: &[(fn() -> (), &'static str)] = &[
(test_global_heap, "test_global_heap"),
(test_allocator_api, "test_allocator_api"),
];

for (test_fn, test_name) in tests {
hprintln!("{}: start", test_name);
test_fn();
hprintln!("{}: pass", test_name);
}

// exit QEMU with a success status
debug::exit(debug::EXIT_SUCCESS);
#[allow(clippy::empty_loop)]
loop {}
}

0 comments on commit b52091a

Please sign in to comment.