Skip to content

Commit 7b1a2ea

Browse files
authored
feat: compatibility with axallocator
feat: compatibility with axallocator
1 parent cf0a059 commit 7b1a2ea

File tree

5 files changed

+19
-281
lines changed

5 files changed

+19
-281
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ tracking = []
2020
bench = []
2121

2222
[dependencies]
23+
axallocator = "0.2"
2324
cfg-if = "1.0"
2425
log = { version = "0.4", optional = true }
2526

src/lib.rs

Lines changed: 4 additions & 271 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@
7575

7676
extern crate alloc;
7777

78-
use core::alloc::Layout;
79-
use core::ptr::NonNull;
80-
8178
// Logging support - conditionally import log crate
8279
#[cfg(feature = "log")]
8380
extern crate log;
@@ -105,40 +102,13 @@ macro_rules! trace {
105102
($($arg:tt)*) => {};
106103
}
107104

105+
pub use axallocator::{
106+
AllocError, AllocResult, BaseAllocator, ByteAllocator, IdAllocator, PageAllocator,
107+
};
108+
108109
/// Default page size for backward compatibility (4KB)
109110
pub const DEFAULT_PAGE_SIZE: usize = 0x1000;
110111

111-
/// The error type used for allocation operations.
112-
///
113-
/// # Examples
114-
///
115-
/// ```
116-
/// use buddy_slab_allocator::AllocError;
117-
///
118-
/// fn handle_error(error: AllocError) {
119-
/// match error {
120-
/// AllocError::InvalidParam => eprintln!("Invalid parameters"),
121-
/// AllocError::MemoryOverlap => eprintln!("Memory regions overlap"),
122-
/// AllocError::NoMemory => eprintln!("Out of memory"),
123-
/// AllocError::NotAllocated => eprintln!("Double free detected"),
124-
/// }
125-
/// }
126-
/// ```
127-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128-
pub enum AllocError {
129-
/// Invalid `size` or alignment (e.g. unaligned)
130-
InvalidParam,
131-
/// Memory added by `add_memory` overlapped with existing memory
132-
MemoryOverlap,
133-
/// No enough memory to allocate
134-
NoMemory,
135-
/// Attempt to deallocate a memory region that was not allocated
136-
NotAllocated,
137-
}
138-
139-
/// A [`Result`] type with [`AllocError`] as the error type.
140-
pub type AllocResult<T = ()> = Result<T, AllocError>;
141-
142112
/// Address translator used by allocators to reason about physical addresses.
143113
///
144114
/// Implementations should provide a stable virtual-to-physical mapping
@@ -165,243 +135,6 @@ pub trait AddrTranslator: Sync {
165135
fn virt_to_phys(&self, va: usize) -> Option<usize>;
166136
}
167137

168-
/// The base allocator trait inherited by other allocator traits.
169-
///
170-
/// Provides common initialization methods for all allocator types.
171-
pub trait BaseAllocator {
172-
/// Initialize the allocator with a free memory region.
173-
///
174-
/// # Arguments
175-
///
176-
/// * `start` - Starting address of the memory region
177-
/// * `size` - Size of the memory region in bytes
178-
///
179-
/// # Examples
180-
///
181-
/// ```
182-
/// # use buddy_slab_allocator::BaseAllocator;
183-
/// # struct MyAllocator;
184-
/// # impl BaseAllocator for MyAllocator {
185-
/// # fn init(&mut self, start: usize, size: usize) {}
186-
/// # fn add_memory(&mut self, start: usize, size: usize) -> buddy_slab_allocator::AllocResult { Ok(()) }
187-
/// # }
188-
/// let mut alloc = MyAllocator;
189-
/// alloc.init(0x8000_0000, 16 * 1024 * 1024);
190-
/// ```
191-
fn init(&mut self, start: usize, size: usize);
192-
193-
/// Add a free memory region to the allocator.
194-
///
195-
/// # Arguments
196-
///
197-
/// * `start` - Starting address of the memory region
198-
/// * `size` - Size of the memory region in bytes
199-
///
200-
/// # Returns
201-
///
202-
/// Returns `Ok(())` on success, or an error if the region overlaps
203-
/// with existing memory.
204-
fn add_memory(&mut self, start: usize, size: usize) -> AllocResult;
205-
}
206-
207-
/// Byte-granularity allocator for arbitrary-size allocations.
208-
///
209-
/// Provides methods for allocating and deallocating memory with
210-
/// byte-level granularity.
211-
pub trait ByteAllocator {
212-
/// Allocate memory with the given size (in bytes) and alignment.
213-
///
214-
/// # Arguments
215-
///
216-
/// * `layout` - Memory layout specifying size and alignment requirements
217-
///
218-
/// # Returns
219-
///
220-
/// Returns a pointer to the allocated memory on success, or an error
221-
/// if allocation fails.
222-
///
223-
/// # Examples
224-
///
225-
/// ```
226-
/// # use buddy_slab_allocator::ByteAllocator;
227-
/// # use core::alloc::Layout;
228-
/// # use core::ptr::NonNull;
229-
/// # struct MyAllocator;
230-
/// # impl ByteAllocator for MyAllocator {
231-
/// # fn alloc(&mut self, layout: Layout) -> buddy_slab_allocator::AllocResult<NonNull<u8>> { Ok(NonNull::dangling()) }
232-
/// # fn dealloc(&mut self, pos: NonNull<u8>, layout: Layout) {}
233-
/// # fn total_bytes(&self) -> usize { 0 }
234-
/// # fn used_bytes(&self) -> usize { 0 }
235-
/// # fn available_bytes(&self) -> usize { 0 }
236-
/// # }
237-
/// let mut alloc = MyAllocator;
238-
/// let layout = Layout::from_size_align(64, 8).unwrap();
239-
/// let ptr = alloc.alloc(layout)?;
240-
/// # Ok::<(), buddy_slab_allocator::AllocError>(())
241-
/// ```
242-
fn alloc(&mut self, layout: Layout) -> AllocResult<NonNull<u8>>;
243-
244-
/// Deallocate memory at the given position, size, and alignment.
245-
///
246-
/// # Arguments
247-
///
248-
/// * `pos` - Pointer to the memory to deallocate
249-
/// * `layout` - Memory layout specifying size and alignment requirements
250-
///
251-
/// # Safety
252-
///
253-
/// The pointer must have been previously allocated from this allocator
254-
/// with the same layout.
255-
fn dealloc(&mut self, pos: NonNull<u8>, layout: Layout);
256-
257-
/// Returns total memory size in bytes managed by this allocator.
258-
fn total_bytes(&self) -> usize;
259-
260-
/// Returns allocated memory size in bytes.
261-
fn used_bytes(&self) -> usize;
262-
263-
/// Returns available memory size in bytes.
264-
fn available_bytes(&self) -> usize;
265-
}
266-
267-
/// Page-granularity allocator for managing memory in pages.
268-
///
269-
/// Provides methods for allocating and deallocating contiguous pages
270-
/// of memory with specific alignment requirements.
271-
pub trait PageAllocator: BaseAllocator {
272-
/// The size of a memory page in bytes (must be a power of two).
273-
const PAGE_SIZE: usize;
274-
275-
/// Allocate contiguous memory pages with given count and alignment (in bytes).
276-
///
277-
/// # Arguments
278-
///
279-
/// * `num_pages` - Number of pages to allocate
280-
/// * `alignment` - Alignment requirement in bytes (must be power of two)
281-
///
282-
/// # Returns
283-
///
284-
/// Returns the starting address of the allocated pages on success,
285-
/// or an error if allocation fails.
286-
///
287-
/// # Examples
288-
///
289-
/// ```
290-
/// # use buddy_slab_allocator::{PageAllocator, BaseAllocator};
291-
/// # struct MyAllocator;
292-
/// # impl BaseAllocator for MyAllocator {
293-
/// # fn init(&mut self, start: usize, size: usize) {}
294-
/// # fn add_memory(&mut self, start: usize, size: usize) -> buddy_slab_allocator::AllocResult { Ok(()) }
295-
/// # }
296-
/// # impl PageAllocator for MyAllocator {
297-
/// # const PAGE_SIZE: usize = 0x1000;
298-
/// # fn alloc_pages(&mut self, num_pages: usize, alignment: usize) -> buddy_slab_allocator::AllocResult<usize> { Ok(0) }
299-
/// # fn dealloc_pages(&mut self, pos: usize, num_pages: usize) {}
300-
/// # fn alloc_pages_at(&mut self, base: usize, num_pages: usize, alignment: usize) -> buddy_slab_allocator::AllocResult<usize> { Ok(0) }
301-
/// # fn total_pages(&self) -> usize { 0 }
302-
/// # fn used_pages(&self) -> usize { 0 }
303-
/// # fn available_pages(&self) -> usize { 0 }
304-
/// # }
305-
/// let mut alloc = MyAllocator;
306-
/// let addr = alloc.alloc_pages(4, 0x1000)?;
307-
/// # Ok::<(), buddy_slab_allocator::AllocError>(())
308-
/// ```
309-
fn alloc_pages(&mut self, num_pages: usize, alignment: usize) -> AllocResult<usize>;
310-
311-
/// Deallocate contiguous memory pages with given position and count.
312-
///
313-
/// # Arguments
314-
///
315-
/// * `pos` - Starting address of the pages to deallocate
316-
/// * `num_pages` - Number of pages to deallocate
317-
///
318-
/// # Safety
319-
///
320-
/// The address range must have been previously allocated from this allocator.
321-
fn dealloc_pages(&mut self, pos: usize, num_pages: usize);
322-
323-
/// Allocate contiguous memory pages with given base address, count and alignment (in bytes).
324-
///
325-
/// # Arguments
326-
///
327-
/// * `base` - Desired starting address for allocation
328-
/// * `num_pages` - Number of pages to allocate
329-
/// * `alignment` - Alignment requirement in bytes (must be power of two)
330-
///
331-
/// # Returns
332-
///
333-
/// Returns the starting address of the allocated pages on success,
334-
/// or an error if the region cannot be allocated at the specified base.
335-
fn alloc_pages_at(
336-
&mut self,
337-
base: usize,
338-
num_pages: usize,
339-
alignment: usize,
340-
) -> AllocResult<usize>;
341-
342-
/// Returns the total number of memory pages managed by this allocator.
343-
fn total_pages(&self) -> usize;
344-
345-
/// Returns the number of allocated memory pages.
346-
fn used_pages(&self) -> usize;
347-
348-
/// Returns the number of available memory pages.
349-
fn available_pages(&self) -> usize;
350-
}
351-
352-
/// ID allocator for managing unique identifiers (e.g., thread IDs).
353-
///
354-
/// Provides methods for allocating and deallocating unique IDs with
355-
/// alignment constraints.
356-
pub trait IdAllocator: BaseAllocator {
357-
/// Allocate contiguous IDs with given count and alignment.
358-
///
359-
/// # Arguments
360-
///
361-
/// * `count` - Number of IDs to allocate
362-
/// * `alignment` - Alignment requirement for the starting ID
363-
///
364-
/// # Returns
365-
///
366-
/// Returns the starting ID on success, or an error if allocation fails.
367-
fn alloc_id(&mut self, count: usize, alignment: usize) -> AllocResult<usize>;
368-
369-
/// Deallocate contiguous IDs with given position and count.
370-
///
371-
/// # Arguments
372-
///
373-
/// * `start_id` - Starting ID of the range to deallocate
374-
/// * `count` - Number of IDs to deallocate
375-
///
376-
/// # Safety
377-
///
378-
/// The ID range must have been previously allocated from this allocator.
379-
fn dealloc_id(&mut self, start_id: usize, count: usize);
380-
381-
/// Checks whether the given ID is currently allocated.
382-
fn is_allocated(&self, id: usize) -> bool;
383-
384-
/// Mark the given ID as allocated and prevent it from being reallocated.
385-
///
386-
/// # Arguments
387-
///
388-
/// * `id` - The ID to mark as permanently allocated
389-
///
390-
/// # Returns
391-
///
392-
/// Returns `Ok(())` on success, or an error if the ID is already allocated.
393-
fn alloc_fixed_id(&mut self, id: usize) -> AllocResult;
394-
395-
/// Returns the maximum number of IDs supported by this allocator.
396-
fn size(&self) -> usize;
397-
398-
/// Returns the number of currently allocated IDs.
399-
fn used(&self) -> usize;
400-
401-
/// Returns the number of available IDs.
402-
fn available(&self) -> usize;
403-
}
404-
405138
#[inline]
406139
#[allow(dead_code)]
407140
const fn align_down(pos: usize, align: usize) -> usize {

src/slab/slab_byte_allocator.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::ptr::NonNull;
99
#[cfg(feature = "log")]
1010
use log::warn;
1111

12-
use crate::{AllocError, AllocResult, ByteAllocator};
12+
use crate::{AllocError, AllocResult, BaseAllocator, ByteAllocator};
1313

1414
// Re-export public types from sibling modules
1515
pub use super::slab_cache::SlabCache;
@@ -151,6 +151,15 @@ impl<const PAGE_SIZE: usize> Default for SlabByteAllocator<PAGE_SIZE> {
151151
}
152152
}
153153

154+
// This implementation is never called, so no-op implementations are fine
155+
impl<const PAGE_SIZE: usize> BaseAllocator for SlabByteAllocator<PAGE_SIZE> {
156+
fn init(&mut self, _start: usize, _size: usize) {}
157+
158+
fn add_memory(&mut self, _start: usize, _size: usize) -> AllocResult {
159+
Ok(())
160+
}
161+
}
162+
154163
impl<const PAGE_SIZE: usize> ByteAllocator for SlabByteAllocator<PAGE_SIZE> {
155164
fn alloc(&mut self, layout: Layout) -> AllocResult<NonNull<u8>> {
156165
let size_class = SizeClass::from_layout(layout).ok_or(AllocError::InvalidParam)?;

tests/dma32_pages_test.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,8 @@ fn test_alloc_dma32_pages_uninitialized() {
4949
// Try to allocate pages - should fail because allocator is not initialized
5050
let result = allocator.alloc_dma32_pages(1, PAGE_SIZE);
5151
assert!(
52-
result.is_err(),
53-
"Expected error when allocating from uninitialized allocator"
54-
);
55-
assert_eq!(
56-
result.unwrap_err(),
57-
AllocError::NoMemory,
58-
"Expected NoMemory error"
52+
matches!(result, Err(AllocError::NoMemory)),
53+
"Expected NoMemory error when allocating from uninitialized allocator"
5954
);
6055
}
6156

tests/integration_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,12 @@ fn test_error_conditions() {
356356

357357
// Test invalid parameter
358358
let result = allocator.alloc_pages(0, PAGE_SIZE);
359-
assert_eq!(result, Err(AllocError::InvalidParam));
359+
assert!(matches!(result, Err(AllocError::InvalidParam)));
360360

361361
// Test allocation too large
362362
let huge_pages = TEST_HEAP_SIZE / PAGE_SIZE + 1000;
363363
let result = allocator.alloc_pages(huge_pages, PAGE_SIZE);
364-
assert_eq!(result, Err(AllocError::NoMemory));
364+
assert!(matches!(result, Err(AllocError::NoMemory)));
365365

366366
dealloc_test_heap(heap_ptr, heap_layout);
367367
}

0 commit comments

Comments
 (0)