diff --git a/Kconfig b/Kconfig index 0d99cb40..9a3ed888 100644 --- a/Kconfig +++ b/Kconfig @@ -19,4 +19,16 @@ config RUST help This option enables the use of applications written in Rust. +if RUST + +config RUST_ALLOC + bool "Support an allocator in Rust code" + help + If enabled, the Rust zephyr support library will include support for + an allocator. This allocator will use the currently configured + Zephyr allocator (malloc/free). This this enabled, Rust + applications can use the `alloc` crate. + +endif # RUST + endmenu diff --git a/zephyr/src/alloc.rs b/zephyr/src/alloc.rs new file mode 100644 index 00000000..8cc1c161 --- /dev/null +++ b/zephyr/src/alloc.rs @@ -0,0 +1,41 @@ +//! A Rust global allocator that uses the stdlib allocator in Zephyr + +// This entire module is only use if CONFIG_RUST_ALLOC is enabled. +extern crate alloc; + +use core::alloc::{GlobalAlloc, Layout}; + +use alloc::alloc::handle_alloc_error; + +/// Define size_t, as it isn't defined within the FFI. +#[allow(non_camel_case_types)] +type c_size_t = usize; + +extern "C" { + fn malloc(size: c_size_t) -> *mut u8; + fn free(ptr: *mut u8); +} + +pub struct ZephyrAllocator; + +unsafe impl GlobalAlloc for ZephyrAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let size = layout.size(); + let align = layout.align(); + + // The C allocation library assumes an alignment of 8. For now, just panic if this cannot + // be satistifed. + if align > 8 { + handle_alloc_error(layout); + } + + malloc(size) + } + + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + free(ptr) + } +} + +#[global_allocator] +static ZEPHYR_ALLOCATOR: ZephyrAllocator = ZephyrAllocator; diff --git a/zephyr/src/lib.rs b/zephyr/src/lib.rs index 22c493f7..b26c001c 100644 --- a/zephyr/src/lib.rs +++ b/zephyr/src/lib.rs @@ -129,3 +129,7 @@ pub mod raw { pub mod _export { pub use core::format_args; } + +/// If allocation has been requested, provide the allocator. +#[cfg(CONFIG_RUST_ALLOC)] +mod alloc;