blob: eab3bc420cd440daee42131d8743961acc7be9ac [file] [log] [blame]
Pierre-Clément Tosifc531152022-10-20 12:22:23 +01001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Heap implementation.
16
Pierre-Clément Tosi54e71d02022-12-08 13:57:43 +000017use core::alloc::GlobalAlloc as _;
18use core::alloc::Layout;
19use core::ffi::c_void;
20use core::mem;
21use core::num::NonZeroUsize;
22use core::ptr;
23use core::ptr::NonNull;
24
Pierre-Clément Tosifc531152022-10-20 12:22:23 +010025use buddy_system_allocator::LockedHeap;
26
27#[global_allocator]
28static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
29
30static mut HEAP: [u8; 65536] = [0; 65536];
31
32pub unsafe fn init() {
33 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
34}
Pierre-Clément Tosi54e71d02022-12-08 13:57:43 +000035
36#[no_mangle]
37unsafe extern "C" fn malloc(size: usize) -> *mut c_void {
38 malloc_(size).map_or(ptr::null_mut(), |p| p.cast::<c_void>().as_ptr())
39}
40
41#[no_mangle]
42unsafe extern "C" fn free(ptr: *mut c_void) {
43 if let Some(ptr) = NonNull::new(ptr).map(|p| p.cast::<usize>().as_ptr().offset(-1)) {
44 if let Some(size) = NonZeroUsize::new(*ptr) {
45 if let Some(layout) = malloc_layout(size) {
46 HEAP_ALLOCATOR.dealloc(ptr as *mut u8, layout);
47 }
48 }
49 }
50}
51
52unsafe fn malloc_(size: usize) -> Option<NonNull<usize>> {
53 let size = NonZeroUsize::new(size)?.checked_add(mem::size_of::<usize>())?;
54 let ptr = HEAP_ALLOCATOR.alloc(malloc_layout(size)?);
55 let ptr = NonNull::new(ptr)?.cast::<usize>().as_ptr();
56 *ptr = size.get();
57 NonNull::new(ptr.offset(1))
58}
59
60fn malloc_layout(size: NonZeroUsize) -> Option<Layout> {
61 const ALIGN: usize = mem::size_of::<u64>();
62 Layout::from_size_align(size.get(), ALIGN).ok()
63}