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;
31#[cfg(feature = "tlsf")]
32pub use tlsf::TlsfByteAllocator;
33
34use core::alloc::Layout;
35use core::ptr::NonNull;
36
37#[cfg(feature = "axerrno")]
38use axerrno::AxError;
39
40#[derive(Debug)]
42pub enum AllocError {
43 InvalidParam,
45 MemoryOverlap,
47 NoMemory,
49 NotAllocated,
51}
52
53#[cfg(feature = "axerrno")]
54impl From<AllocError> for AxError {
55 fn from(value: AllocError) -> Self {
56 match value {
57 AllocError::NoMemory => AxError::NoMemory,
58 _ => AxError::InvalidInput,
59 }
60 }
61}
62
63pub type AllocResult<T = ()> = Result<T, AllocError>;
65
66pub trait BaseAllocator {
68 fn init(&mut self, start: usize, size: usize);
70
71 fn add_memory(&mut self, start: usize, size: usize) -> AllocResult;
73}
74
75pub trait ByteAllocator: BaseAllocator {
77 fn alloc(&mut self, layout: Layout) -> AllocResult<NonNull<u8>>;
79
80 fn dealloc(&mut self, pos: NonNull<u8>, layout: Layout);
82
83 fn total_bytes(&self) -> usize;
85
86 fn used_bytes(&self) -> usize;
88
89 fn available_bytes(&self) -> usize;
91}
92
93pub trait PageAllocator: BaseAllocator {
95 const PAGE_SIZE: usize;
97
98 fn alloc_pages(&mut self, num_pages: usize, align_pow2: usize) -> AllocResult<usize>;
100
101 fn dealloc_pages(&mut self, pos: usize, num_pages: usize);
103
104 fn alloc_pages_at(
106 &mut self,
107 base: usize,
108 num_pages: usize,
109 align_pow2: usize,
110 ) -> AllocResult<usize>;
111
112 fn total_pages(&self) -> usize;
114
115 fn used_pages(&self) -> usize;
117
118 fn available_pages(&self) -> usize;
120}
121
122pub trait IdAllocator: BaseAllocator {
124 fn alloc_id(&mut self, count: usize, align_pow2: usize) -> AllocResult<usize>;
126
127 fn dealloc_id(&mut self, start_id: usize, count: usize);
129
130 fn is_allocated(&self, id: usize) -> bool;
132
133 fn alloc_fixed_id(&mut self, id: usize) -> AllocResult;
135
136 fn size(&self) -> usize;
138
139 fn used(&self) -> usize;
141
142 fn available(&self) -> usize;
144}
145
146#[inline]
147#[allow(dead_code)]
148const fn align_down(pos: usize, align: usize) -> usize {
149 pos & !(align - 1)
150}
151
152#[inline]
153#[allow(dead_code)]
154const fn align_up(pos: usize, align: usize) -> usize {
155 (pos + align - 1) & !(align - 1)
156}
157
158#[inline]
162#[allow(dead_code)]
163const fn is_aligned(base_addr: usize, align: usize) -> bool {
164 base_addr & (align - 1) == 0
165}
166
167#[cfg(feature = "allocator_api")]
168mod allocator_api {
169 extern crate alloc;
170
171 use super::ByteAllocator;
172 use alloc::rc::Rc;
173 use core::alloc::{AllocError, Allocator, Layout};
174 use core::cell::RefCell;
175 use core::ptr::NonNull;
176
177 pub struct AllocatorRc<A: ByteAllocator>(Rc<RefCell<A>>);
179
180 impl<A: ByteAllocator> AllocatorRc<A> {
181 pub fn new(mut inner: A, pool: &mut [u8]) -> Self {
183 inner.init(pool.as_mut_ptr() as usize, pool.len());
184 Self(Rc::new(RefCell::new(inner)))
185 }
186 }
187
188 unsafe impl<A: ByteAllocator> Allocator for AllocatorRc<A> {
189 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
190 match layout.size() {
191 0 => Ok(NonNull::slice_from_raw_parts(NonNull::dangling(), 0)),
192 size => {
193 let raw_addr = self.0.borrow_mut().alloc(layout).map_err(|_| AllocError)?;
194 Ok(NonNull::slice_from_raw_parts(raw_addr, size))
195 }
196 }
197 }
198
199 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
200 self.0.borrow_mut().dealloc(ptr, layout)
201 }
202 }
203
204 impl<A: ByteAllocator> Clone for AllocatorRc<A> {
205 fn clone(&self) -> Self {
206 Self(self.0.clone())
207 }
208 }
209}
210
211#[cfg(feature = "allocator_api")]
212pub use allocator_api::AllocatorRc;