diff --git a/CHANGELOG.md b/CHANGELOG.md index 12fd89e..0710ceb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- Implemented [`Allocator`] for `Heap` with the `allocator_api` crate feature. + This feature requires a nightly toolchain for the unstable [`allocator_api`] + compiler feature. + +[`Allocator`]: https://doc.rust-lang.org/core/alloc/trait.Allocator.html +[`allocator_api`]: https://doc.rust-lang.org/beta/unstable-book/library-features/allocator-api.html + +### Changed + - Updated `linked_list_allocator` dependency to 0.10.5, which allows compiling with stable rust. diff --git a/Cargo.toml b/Cargo.toml index 3009541..eeae610 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,9 @@ license = "MIT OR Apache-2.0" name = "embedded-alloc" version = "0.5.0" +[features] +allocator_api = [] + [dependencies] critical-section = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 27a9a7d..c92a123 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../README.md")] #![no_std] +#![cfg_attr(feature = "allocator_api", feature(allocator_api, alloc_layout_extra))] use core::alloc::{GlobalAlloc, Layout}; use core::cell::RefCell; @@ -88,3 +89,40 @@ unsafe impl GlobalAlloc for Heap { }); } } + +#[cfg(feature = "allocator_api")] +mod allocator_api { + use core::{ + alloc::{AllocError, Allocator, Layout}, + ptr::NonNull, + }; + + use crate::Heap; + + unsafe impl Allocator for Heap { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + match layout.size() { + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + size => critical_section::with(|cs| { + self.heap + .borrow(cs) + .borrow_mut() + .allocate_first_fit(layout) + .map(|allocation| NonNull::slice_from_raw_parts(allocation, size)) + .map_err(|_| AllocError) + }), + } + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + if layout.size() != 0 { + critical_section::with(|cs| { + self.heap + .borrow(cs) + .borrow_mut() + .deallocate(NonNull::new_unchecked(ptr.as_ptr()), layout) + }); + } + } + } +}