88//! extern crate collections;
99//!
1010//! use collections::Vec;
11+ //! use alloc_cortex_m::CortexMHeap;
12+ //!
13+ //! #[global_allocator]
14+ //! static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
1115//!
1216//! // These symbols come from a linker script
1317//! extern "C" {
1822//! #[no_mangle]
1923//! pub fn main() -> ! {
2024//! // Initialize the heap BEFORE you use the allocator
21- //! unsafe { alloc_cortex_m:: init(&mut _heap_start, &mut _heap_end) }
25+ //! unsafe { ALLOCATOR. init(_heap_start, _heap_end - _heap_start ) }
2226//!
2327//! let mut xs = Vec::new();
2428//! xs.push(1);
3741//! _heap_end = ORIGIN(SRAM) + LENGTH(SRAM) - _stack_size;
3842//! ```
3943
40- #![ allocator]
41- #![ feature( allocator) ]
4244#![ feature( const_fn) ]
4345#![ no_std]
46+ #![ feature( alloc, allocator_api) ]
4447
4548extern crate cortex_m;
4649extern crate linked_list_allocator;
50+ extern crate alloc;
4751
48- use core :: { cmp , ptr } ;
52+ use alloc :: allocator :: { Alloc , Layout , AllocErr } ;
4953
5054use linked_list_allocator:: Heap ;
5155use cortex_m:: interrupt:: Mutex ;
5256
53- /// A global UNINITIALIZED heap allocator
54- ///
55- /// You must initialize this heap using the
56- /// [`init`](struct.Heap.html#method.init) method before using the allocator.
57- static HEAP : Mutex < Heap > = Mutex :: new ( Heap :: empty ( ) ) ;
58-
59- /// Initializes the heap
60- ///
61- /// This function must be called BEFORE you run any code that makes use of the
62- /// allocator.
63- ///
64- /// `start_addr` is the address where the heap will be located.
65- ///
66- /// `end_addr` points to the end of the heap.
67- ///
68- /// Note that:
69- ///
70- /// - The heap grows "upwards", towards larger addresses. Thus `end_addr` must
71- /// be larger than `start_addr`
72- ///
73- /// - The size of the heap is `(end_addr as usize) - (start_addr as usize)`. The
74- /// allocator won't use the byte at `end_addr`.
75- ///
76- /// # Unsafety
77- ///
78- /// Obey these or Bad Stuff will happen.
79- ///
80- /// - This function must be called exactly ONCE.
81- /// - `end_addr` > `start_addr`
82- pub unsafe fn init ( start_addr : * mut usize , end_addr : * mut usize ) {
83- let start = start_addr as usize ;
84- let end = end_addr as usize ;
85- let size = end - start;
86- HEAP . lock ( |heap| heap. init ( start, size) ) ;
57+ pub struct CortexMHeap {
58+ heap : Mutex < Heap > ,
8759}
8860
89- // Rust allocator interface
90-
91- #[ doc( hidden) ]
92- #[ no_mangle]
93- /// Rust allocation function (c.f. malloc)
94- pub extern "C" fn __rust_allocate ( size : usize , align : usize ) -> * mut u8 {
95- HEAP . lock ( |heap| {
96- heap. allocate_first_fit ( size, align) . expect ( "out of memory" )
97- } )
98- }
61+ impl CortexMHeap {
9962
100- # [ doc ( hidden ) ]
101- # [ no_mangle ]
102- pub extern fn __rust_allocate_zeroed ( size : usize , align : usize ) -> * mut u8 {
103- let ptr = __rust_allocate ( size , align ) ;
104- if !ptr . is_null ( ) {
105- unsafe {
106- ptr :: write_bytes ( ptr , 0 , size ) ;
63+ /// Crate a new UNINITIALIZED heap allocator
64+ ///
65+ /// You must initialize this heap using the
66+ /// [`init`](struct.CortexMHeap.html#method.init) method before using the allocator.
67+ pub const fn empty ( ) -> CortexMHeap {
68+ CortexMHeap {
69+ heap : Mutex :: new ( Heap :: empty ( ) ) ,
10770 }
10871 }
109- ptr
110- }
111-
112- /// Rust de-allocation function (c.f. free)
113- #[ doc( hidden) ]
114- #[ no_mangle]
115- pub extern "C" fn __rust_deallocate ( ptr : * mut u8 , size : usize , align : usize ) {
116- HEAP . lock ( |heap| unsafe { heap. deallocate ( ptr, size, align) } ) ;
117- }
11872
119- /// Rust re-allocation function (c.f. realloc)
120- #[ doc( hidden) ]
121- #[ no_mangle]
122- pub extern "C" fn __rust_reallocate ( ptr : * mut u8 ,
123- size : usize ,
124- new_size : usize ,
125- align : usize )
126- -> * mut u8 {
127-
128- // from: https://github.com/rust-lang/rust/blob/
129- // c66d2380a810c9a2b3dbb4f93a830b101ee49cc2/
130- // src/liballoc_system/lib.rs#L98-L101
131-
132- let new_ptr = __rust_allocate ( new_size, align) ;
133- unsafe { ptr:: copy ( ptr, new_ptr, cmp:: min ( size, new_size) ) } ;
134- __rust_deallocate ( ptr, size, align) ;
135- new_ptr
73+ /// Initializes the heap
74+ ///
75+ /// This function must be called BEFORE you run any code that makes use of the
76+ /// allocator.
77+ ///
78+ /// `start_addr` is the address where the heap will be located.
79+ ///
80+ /// `size` is the size of the heap in bytes.
81+ ///
82+ /// Note that:
83+ ///
84+ /// - The heap grows "upwards", towards larger addresses. Thus `end_addr` must
85+ /// be larger than `start_addr`
86+ ///
87+ /// - The size of the heap is `(end_addr as usize) - (start_addr as usize)`. The
88+ /// allocator won't use the byte at `end_addr`.
89+ ///
90+ /// # Unsafety
91+ ///
92+ /// Obey these or Bad Stuff will happen.
93+ ///
94+ /// - This function must be called exactly ONCE.
95+ /// - `size > 0`
96+ pub unsafe fn init ( & self , start_addr : usize , size : usize ) {
97+ self . heap . lock ( |heap| heap. init ( start_addr, size) ) ;
98+ }
13699}
137100
138- /// Rust re-allocation function which guarantees not to move the data
139- /// somewhere else.
140- #[ doc( hidden) ]
141- #[ no_mangle]
142- pub extern "C" fn __rust_reallocate_inplace ( _ptr : * mut u8 ,
143- size : usize ,
144- _new_size : usize ,
145- _align : usize )
146- -> usize {
147- size
148- }
101+ unsafe impl < ' a > Alloc for & ' a CortexMHeap {
102+ unsafe fn alloc ( & mut self , layout : Layout ) -> Result < * mut u8 , AllocErr > {
103+ self . heap . lock ( |heap| {
104+ heap. allocate_first_fit ( layout)
105+ } )
106+ }
149107
150- /// Some allocators (pool allocators generally) over-allocate. This checks how
151- /// much space there is at a location. Our allocator doesn't over allocate so
152- /// this just returns `size`
153- #[ doc( hidden) ]
154- #[ no_mangle]
155- pub extern "C" fn __rust_usable_size ( size : usize , _align : usize ) -> usize {
156- size
157- }
108+ unsafe fn dealloc ( & mut self , ptr : * mut u8 , layout : Layout ) {
109+ self . heap . lock ( |heap| heap. deallocate ( ptr, layout) ) ;
110+ }
111+ }
0 commit comments