1#![no_std]
12#![cfg_attr(feature = "allocator_api", feature(allocator_api))]
13
14#[cfg(feature = "bitmap")]
15mod bitmap;
16#[cfg(feature = "bitmap")]
17pub use bitmap::BitmapPageAllocator;
18
19#[cfg(feature = "buddy")]
20mod buddy;
21#[cfg(feature = "buddy")]
22pub use buddy::BuddyByteAllocator;
23
24#[cfg(feature = "slab")]
25mod slab;
26#[cfg(feature = "slab")]
27pub use slab::SlabByteAllocator;
28
29#[cfg(feature = "tlsf")]
30mod tlsf;
31use core::{alloc::Layout, ptr::NonNull};
32
33#[cfg(feature = "ax-errno")]
34use ax_errno::AxError;
35#[cfg(feature = "tlsf")]
36pub use tlsf::TlsfByteAllocator;
37
38#[derive(Debug)]
40pub enum AllocError {
41 InvalidParam,
43 MemoryOverlap,
45 NoMemory,
47 NotAllocated,
49}
50
51#[cfg(feature = "ax-errno")]
52impl From<AllocError> for AxError {
53 fn from(value: AllocError) -> Self {
54 match value {
55 AllocError::NoMemory => AxError::NoMemory,
56 _ => AxError::InvalidInput,
57 }
58 }
59}
60
61pub type AllocResult<T = ()> = Result<T, AllocError>;
63
64pub trait BaseAllocator {
66 fn init(&mut self, start: usize, size: usize);
68
69 fn add_memory(&mut self, start: usize, size: usize) -> AllocResult;
71}
72
73pub trait ByteAllocator: BaseAllocator {
75 fn alloc(&mut self, layout: Layout) -> AllocResult<NonNull<u8>>;
77
78 fn dealloc(&mut self, pos: NonNull<u8>, layout: Layout);
80
81 fn total_bytes(&self) -> usize;
83
84 fn used_bytes(&self) -> usize;
86
87 fn available_bytes(&self) -> usize;
89}
90
91pub trait PageAllocator: BaseAllocator {
93 const PAGE_SIZE: usize;
95
96 fn alloc_pages(&mut self, num_pages: usize, align: usize) -> AllocResult<usize>;
100
101 fn dealloc_pages(&mut self, pos: usize, num_pages: usize);
103
104 fn alloc_pages_at(&mut self, base: usize, num_pages: usize, align: usize)
108 -> AllocResult<usize>;
109
110 fn total_pages(&self) -> usize;
112
113 fn used_pages(&self) -> usize;
115
116 fn available_pages(&self) -> usize;
118}
119
120pub trait IdAllocator: BaseAllocator {
122 fn alloc_id(&mut self, count: usize, align_pow2: usize) -> AllocResult<usize>;
124
125 fn dealloc_id(&mut self, start_id: usize, count: usize);
127
128 fn is_allocated(&self, id: usize) -> bool;
130
131 fn alloc_fixed_id(&mut self, id: usize) -> AllocResult;
133
134 fn size(&self) -> usize;
136
137 fn used(&self) -> usize;
139
140 fn available(&self) -> usize;
142}
143
144#[inline]
145#[allow(dead_code)]
146const fn align_down(pos: usize, align: usize) -> usize {
147 pos & !(align - 1)
148}
149
150#[inline]
151#[allow(dead_code)]
152const fn align_up(pos: usize, align: usize) -> usize {
153 (pos + align - 1) & !(align - 1)
154}
155
156#[inline]
160#[allow(dead_code)]
161const fn is_aligned(base_addr: usize, align: usize) -> bool {
162 base_addr & (align - 1) == 0
163}
164
165#[cfg(feature = "allocator_api")]
166mod allocator_api {
167 extern crate alloc;
168
169 use alloc::rc::Rc;
170 use core::{
171 alloc::{AllocError, Allocator, Layout},
172 cell::RefCell,
173 ptr::NonNull,
174 };
175
176 use super::ByteAllocator;
177
178 pub struct AllocatorRc<A: ByteAllocator>(Rc<RefCell<A>>);
180
181 impl<A: ByteAllocator> AllocatorRc<A> {
182 pub fn new(mut inner: A, pool: &mut [u8]) -> Self {
184 inner.init(pool.as_mut_ptr() as usize, pool.len());
185 Self(Rc::new(RefCell::new(inner)))
186 }
187 }
188
189 unsafe impl<A: ByteAllocator> Allocator for AllocatorRc<A> {
190 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
191 match layout.size() {
192 0 => Ok(NonNull::slice_from_raw_parts(NonNull::dangling(), 0)),
193 size => {
194 let raw_addr = self.0.borrow_mut().alloc(layout).map_err(|_| AllocError)?;
195 Ok(NonNull::slice_from_raw_parts(raw_addr, size))
196 }
197 }
198 }
199
200 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
201 self.0.borrow_mut().dealloc(ptr, layout)
202 }
203 }
204
205 impl<A: ByteAllocator> Clone for AllocatorRc<A> {
206 fn clone(&self) -> Self {
207 Self(self.0.clone())
208 }
209 }
210}
211
212#[cfg(feature = "allocator_api")]
213pub use allocator_api::AllocatorRc;