Skip to content

Commit b401dd7

Browse files
committed
Merge branch 'master' of https://github.com/rust-embedded/embedded-alloc into before-conflicts
2 parents 06f1379 + 38d425d commit b401dd7

File tree

7 files changed

+178
-17
lines changed

7 files changed

+178
-17
lines changed

.cargo/config.toml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[target.thumbv7m-none-eabi]
2+
# used to run the qemu_test.rs example with QEMU
3+
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
4+
rustflags = ["-C", "link-arg=-Tlink.x"]

.github/workflows/ci.yml

+16-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,25 @@ jobs:
2424
with:
2525
targets: ${{ matrix.target }}
2626
toolchain: ${{ matrix.toolchain }}
27-
- run: cargo check --target=${{ matrix.target }} --examples
27+
- run: cargo check --target=${{ matrix.target }} --example global_alloc
2828
- if: ${{ matrix.toolchain == 'nightly' }}
2929
run: cargo check --target=${{ matrix.target }} --examples --all-features
3030

31+
test:
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v4
35+
- uses: dtolnay/rust-toolchain@master
36+
with:
37+
targets: thumbv7m-none-eabi
38+
toolchain: nightly
39+
- name: Install QEMU
40+
run: |
41+
sudo apt update
42+
sudo apt install qemu-system-arm
43+
- run: qemu-system-arm --version
44+
- run: cargo run --target thumbv7m-none-eabi --example integration_test --all-features
45+
3146
clippy:
3247
name: Clippy
3348
runs-on: ubuntu-latest

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ name = "embedded-alloc"
2424
version = "0.5.0"
2525

2626
[features]
27-
default = ["llff"]
27+
default = ["llff", "tlsf"]
2828
allocator_api = []
2929

3030
# Use the Two-Level Segregated Fit allocator
@@ -42,3 +42,5 @@ const-default = { version = "1.0.0", default-features = false, optional = true }
4242
[dev-dependencies]
4343
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
4444
cortex-m-rt = "0.7"
45+
cortex-m-semihosting = "0.5"
46+
panic-semihosting = { version = "0.6", features = ["exit"] }

examples/allocator_api.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#![feature(allocator_api)]
2+
#![no_std]
3+
#![no_main]
4+
5+
extern crate alloc;
6+
7+
use alloc::vec::Vec;
8+
use core::mem::MaybeUninit;
9+
use core::panic::PanicInfo;
10+
use cortex_m_rt::entry;
11+
use embedded_alloc::Heap;
12+
13+
// This is not used, but as of 2023-10-29 allocator_api cannot be used without
14+
// a global heap
15+
#[global_allocator]
16+
static HEAP: Heap = Heap::empty();
17+
18+
#[entry]
19+
fn main() -> ! {
20+
const HEAP_SIZE: usize = 16;
21+
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
22+
let heap: Heap = Heap::empty();
23+
unsafe { heap.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
24+
25+
let mut xs = Vec::new_in(heap);
26+
xs.push(1);
27+
28+
#[allow(clippy::empty_loop)]
29+
loop { /* .. */ }
30+
}
31+
32+
#[panic_handler]
33+
fn panic(_: &PanicInfo) -> ! {
34+
loop {}
35+
}

examples/integration_test.rs

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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 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::vec::Vec;
23+
use core::mem::{size_of, MaybeUninit};
24+
use cortex_m_rt::entry;
25+
use cortex_m_semihosting::{debug, hprintln};
26+
use embedded_alloc::Heap;
27+
28+
#[global_allocator]
29+
static HEAP: Heap = Heap::empty();
30+
31+
fn test_global_heap() {
32+
assert_eq!(HEAP.used(), 0);
33+
34+
let mut xs: Vec<i32> = alloc::vec![1];
35+
xs.push(2);
36+
xs.extend(&[3, 4]);
37+
38+
// do not optimize xs
39+
core::hint::black_box(&mut xs);
40+
41+
assert_eq!(xs.as_slice(), &[1, 2, 3, 4]);
42+
assert_eq!(HEAP.used(), size_of::<i32>() * xs.len());
43+
}
44+
45+
fn test_allocator_api() {
46+
// small local heap
47+
const HEAP_SIZE: usize = 16;
48+
let heap_mem: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
49+
let local_heap: Heap = Heap::empty();
50+
unsafe { local_heap.init(heap_mem.as_ptr() as usize, HEAP_SIZE) }
51+
52+
assert_eq!(local_heap.used(), 0);
53+
54+
let mut v: Vec<u16, Heap> = Vec::new_in(local_heap);
55+
v.push(0xCAFE);
56+
v.extend(&[0xDEAD, 0xFEED]);
57+
58+
// do not optimize v
59+
core::hint::black_box(&mut v);
60+
61+
assert_eq!(v.as_slice(), &[0xCAFE, 0xDEAD, 0xFEED]);
62+
}
63+
64+
#[entry]
65+
fn main() -> ! {
66+
{
67+
const HEAP_SIZE: usize = 1024;
68+
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
69+
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
70+
}
71+
72+
#[allow(clippy::type_complexity)]
73+
let tests: &[(fn() -> (), &'static str)] = &[
74+
(test_global_heap, "test_global_heap"),
75+
(test_allocator_api, "test_allocator_api"),
76+
];
77+
78+
for (test_fn, test_name) in tests {
79+
hprintln!("{}: start", test_name);
80+
test_fn();
81+
hprintln!("{}: pass", test_name);
82+
}
83+
84+
// exit QEMU with a success status
85+
debug::exit(debug::EXIT_SUCCESS);
86+
#[allow(clippy::empty_loop)]
87+
loop {}
88+
}

memory.x

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
MEMORY
2+
{
3+
/* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */
4+
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
5+
RAM : ORIGIN = 0x20000000, LENGTH = 64K
6+
}

src/lib.rs

+26-15
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,14 @@ mod llff {
7575
pub fn free(&self) -> usize {
7676
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().free())
7777
}
78-
}
7978

80-
unsafe impl GlobalAlloc for Heap {
81-
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
79+
unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
8280
critical_section::with(|cs| {
8381
self.heap
8482
.borrow(cs)
8583
.borrow_mut()
8684
.allocate_first_fit(layout)
8785
.ok()
88-
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
8986
})
9087
}
9188

@@ -99,6 +96,17 @@ mod llff {
9996
}
10097
}
10198

99+
unsafe impl GlobalAlloc for Heap {
100+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
101+
self.alloc(layout)
102+
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
103+
}
104+
105+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
106+
self.dealloc(ptr, layout);
107+
}
108+
}
109+
102110
#[cfg(feature = "allocator_api")]
103111
mod allocator_api {
104112
use super::*;
@@ -192,17 +200,9 @@ mod tlsf {
192200
.insert_free_block_ptr(block.into());
193201
});
194202
}
195-
}
196203

197-
unsafe impl GlobalAlloc for Heap {
198-
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
199-
critical_section::with(|cs| {
200-
self.heap
201-
.borrow(cs)
202-
.borrow_mut()
203-
.allocate(layout)
204-
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
205-
})
204+
unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
205+
critical_section::with(|cs| self.heap.borrow(cs).borrow_mut().allocate(layout))
206206
}
207207

208208
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
@@ -211,7 +211,18 @@ mod tlsf {
211211
.borrow(cs)
212212
.borrow_mut()
213213
.deallocate(NonNull::new_unchecked(ptr), layout.align())
214-
});
214+
})
215+
}
216+
}
217+
218+
unsafe impl GlobalAlloc for Heap {
219+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
220+
self.alloc(layout)
221+
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
222+
}
223+
224+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
225+
self.dealloc(ptr, layout)
215226
}
216227
}
217228

0 commit comments

Comments
 (0)