1#![no_std]
8
9#[cfg(not(is_kernel))]
10extern crate alloc;
11
12use core::alloc::Layout;
13use core::ptr::NonNull;
14
15mod allocator;
16mod boxed;
17
18pub use allocator::{AllocError, Allocator, DefaultAllocator, NoOpAllocator};
19pub use boxed::Box;
20
21#[cfg(not(is_kernel))]
27pub unsafe fn alloc(layout: Layout) -> Option<NonNull<u8>> {
28 debug_assert!(layout.size() > 0);
29 let ptr = unsafe { alloc::alloc::alloc(layout) };
30 NonNull::new(ptr)
31}
32
33#[cfg(not(is_kernel))]
40pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
41 debug_assert!(layout.size() > 0);
42 unsafe { alloc::alloc::dealloc(ptr, layout) }
43}
44
45#[cfg(not(is_kernel))]
54pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> Option<NonNull<u8>> {
55 debug_assert!(layout.size() > 0);
56 debug_assert!(new_size > 0);
57 let ptr = unsafe { alloc::alloc::realloc(ptr, layout, new_size) };
58 NonNull::new(ptr)
59}
60
61#[cfg(not(is_kernel))]
67pub unsafe fn alloc_zeroed(layout: Layout) -> Option<NonNull<u8>> {
68 debug_assert!(layout.size() > 0);
69 let ptr = unsafe { alloc::alloc::alloc_zeroed(layout) };
70 NonNull::new(ptr)
71}
72
73#[cfg(is_kernel)]
79pub unsafe fn alloc(layout: Layout) -> Option<NonNull<u8>> {
80 debug_assert!(layout.size() > 0);
81 unsafe extern "C" {
82 fn malloc(size: usize) -> *mut core::ffi::c_void;
83 fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void;
84 }
85 let ptr = if layout.align() <= 8 {
86 unsafe { malloc(layout.size()) as *mut u8 }
87 } else {
88 unsafe { memalign(layout.align(), layout.size()) as *mut u8 }
89 };
90 NonNull::new(ptr)
91}
92
93#[cfg(is_kernel)]
100pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
101 debug_assert!(layout.size() > 0);
102 unsafe extern "C" {
103 fn free(ptr: *mut core::ffi::c_void);
104 }
105 unsafe { free(ptr as *mut core::ffi::c_void) }
106}
107
108#[cfg(is_kernel)]
117pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> Option<NonNull<u8>> {
118 debug_assert!(layout.size() > 0);
119 debug_assert!(new_size > 0);
120
121 let new_layout = Layout::from_size_align(new_size, layout.align()).ok()?;
124 let new_ptr = unsafe { crate::alloc(new_layout) };
125
126 if let Some(new_p) = new_ptr {
127 let copy_size = core::cmp::min(layout.size(), new_size);
128 unsafe {
129 core::ptr::copy_nonoverlapping(ptr, new_p.as_ptr(), copy_size);
130 crate::dealloc(ptr, layout);
131 }
132 }
133 new_ptr
134}
135
136#[cfg(is_kernel)]
142pub unsafe fn alloc_zeroed(layout: Layout) -> Option<NonNull<u8>> {
143 debug_assert!(layout.size() > 0);
144 if layout.align() <= 8 {
145 unsafe extern "C" {
146 fn calloc(nmemb: usize, size: usize) -> *mut core::ffi::c_void;
147 }
148 let ptr = unsafe { calloc(1, layout.size()) as *mut u8 };
149 NonNull::new(ptr)
150 } else {
151 let ptr = unsafe { crate::alloc(layout) };
152 if let Some(p) = ptr {
153 unsafe {
154 core::ptr::write_bytes(p.as_ptr(), 0, layout.size());
155 }
156 }
157 ptr
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
166 fn test_kalloc_alloc() {
167 let layout = Layout::from_size_align(10, 1).unwrap();
168 unsafe {
169 let ptr = crate::alloc(layout).unwrap();
170 crate::dealloc(ptr.as_ptr(), layout);
171 }
172 }
173
174 #[test]
175 fn test_kalloc_realloc() {
176 let layout = Layout::from_size_align(10, 1).unwrap();
177 unsafe {
178 let ptr = crate::alloc(layout).unwrap();
179 let new_ptr = crate::realloc(ptr.as_ptr(), layout, 20).unwrap();
180 crate::dealloc(new_ptr.as_ptr(), Layout::from_size_align(20, 1).unwrap());
181 }
182 }
183
184 #[test]
185 fn test_kalloc_alloc_zeroed() {
186 let layout = Layout::from_size_align(10, 1).unwrap();
187 unsafe {
188 let ptr = crate::alloc_zeroed(layout).unwrap();
189 let slice = core::slice::from_raw_parts(ptr.as_ptr(), 10);
190 assert!(slice.iter().all(|&b| b == 0));
191 crate::dealloc(ptr.as_ptr(), layout);
192 }
193 }
194}