blob: e412f69cc501d9fb6f0ca83ad9dfe49bb49fdb6b [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 Tosidb74cb12022-12-08 13:56:25 +000017use alloc::alloc::alloc;
18use alloc::alloc::Layout;
19use alloc::boxed::Box;
20
Pierre-Clément Tosi54e71d02022-12-08 13:57:43 +000021use core::alloc::GlobalAlloc as _;
Pierre-Clément Tosi54e71d02022-12-08 13:57:43 +000022use core::ffi::c_void;
23use core::mem;
24use core::num::NonZeroUsize;
25use core::ptr;
26use core::ptr::NonNull;
27
Pierre-Clément Tosifc531152022-10-20 12:22:23 +010028use buddy_system_allocator::LockedHeap;
29
30#[global_allocator]
31static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
32
33static mut HEAP: [u8; 65536] = [0; 65536];
34
35pub unsafe fn init() {
36 HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
37}
Pierre-Clément Tosi54e71d02022-12-08 13:57:43 +000038
Pierre-Clément Tosidb74cb12022-12-08 13:56:25 +000039/// Allocate an aligned but uninitialized slice of heap.
40pub fn aligned_boxed_slice(size: usize, align: usize) -> Option<Box<[u8]>> {
41 let size = NonZeroUsize::new(size)?.get();
42 let layout = Layout::from_size_align(size, align).ok()?;
43 // SAFETY - We verify that `size` and the returned `ptr` are non-null.
44 let ptr = unsafe { alloc(layout) };
45 let ptr = NonNull::new(ptr)?.as_ptr();
46 let slice_ptr = ptr::slice_from_raw_parts_mut(ptr, size);
47
48 // SAFETY - The memory was allocated using the proper layout by our global_allocator.
49 Some(unsafe { Box::from_raw(slice_ptr) })
50}
51
Pierre-Clément Tosi54e71d02022-12-08 13:57:43 +000052#[no_mangle]
53unsafe extern "C" fn malloc(size: usize) -> *mut c_void {
54 malloc_(size).map_or(ptr::null_mut(), |p| p.cast::<c_void>().as_ptr())
55}
56
57#[no_mangle]
58unsafe extern "C" fn free(ptr: *mut c_void) {
59 if let Some(ptr) = NonNull::new(ptr).map(|p| p.cast::<usize>().as_ptr().offset(-1)) {
60 if let Some(size) = NonZeroUsize::new(*ptr) {
61 if let Some(layout) = malloc_layout(size) {
62 HEAP_ALLOCATOR.dealloc(ptr as *mut u8, layout);
63 }
64 }
65 }
66}
67
68unsafe fn malloc_(size: usize) -> Option<NonNull<usize>> {
69 let size = NonZeroUsize::new(size)?.checked_add(mem::size_of::<usize>())?;
70 let ptr = HEAP_ALLOCATOR.alloc(malloc_layout(size)?);
71 let ptr = NonNull::new(ptr)?.cast::<usize>().as_ptr();
72 *ptr = size.get();
73 NonNull::new(ptr.offset(1))
74}
75
76fn malloc_layout(size: NonZeroUsize) -> Option<Layout> {
77 const ALIGN: usize = mem::size_of::<u64>();
78 Layout::from_size_align(size.get(), ALIGN).ok()
79}