Understanding the meaning of "available_bytes"
I built a simple test of the buddy-alloc, which builds a 1MiB heap, and tries to allocate all of it.
First thing I noticed is that the heap I end up with in the allocator is smaller than my 1MiB heap.
I think this is due to the base_ptr getting aligned past the start of my buffer, but I'd like to confirm that is the case, or if that isn't expected.
The second thing I noticed is that if I try to allocate all the available bytes, I get back a null pointer from the call to malloc, this I didn't expect, as the call to available_bytes claims I have this many bytes to allocate.
I may have overlooked some fixed overhead each allocation needs, although perhaps if there is such overhead, it would make sense for available_bytes to reflect that in its response?
Here is a small test case that highlights what I'm seeing:
use buddy_alloc::buddy_alloc::BuddyAlloc;
use buddy_alloc::BuddyAllocParam;
fn main() {
let (layout, mut alloc) = unsafe {
let layout = std::alloc::Layout::from_size_align_unchecked(1<<20, 4096);
let data = std::alloc::alloc(layout) as *mut u8;
let alloc = BuddyAlloc::new(BuddyAllocParam::new(data, layout.size(), layout.align()));
(layout, alloc)
};
println!("layout size: {}. allocator size {}.", layout.size(), alloc.available_bytes());
let ptr = alloc.malloc(alloc.available_bytes());
assert!(! ptr.is_null());
alloc.free(ptr);
}
Further digging I come up with this program which highlights things a bit more clearly:
use buddy_alloc::buddy_alloc::BuddyAlloc;
use buddy_alloc::BuddyAllocParam;
fn main() {
let (layout, mut alloc) = unsafe {
let layout = std::alloc::Layout::from_size_align_unchecked(1<<20, 4096);
let data = std::alloc::alloc(layout) as *mut u8;
let alloc = BuddyAlloc::new(BuddyAllocParam::new(data, layout.size(), layout.align()));
(layout, alloc)
};
println!("layout size: {}. allocator size {}.", layout.size(), alloc.available_bytes());
let ptr = alloc.malloc((layout.align()/2)+1+(alloc.available_bytes() / 2));
assert!(! ptr.is_null());
alloc.free(ptr);
}
It would appear we can allocate up to (layout.align()/2)+(alloc.available_bytes() / 2) bytes from an empty allocator, but not one byte more. That makes sense given the buddy algorithm, but it still indicates that perhaps available_bytes is unclear in its purpose.
IMO we can add comments to hint users. And we can add another function to return the maximum allocatable size.
/// Returns the maximum size that this allocator can allocate at once.
fn max_allocate_size()
/// Returns the number of bytes currently available for allocation by this allocator.
/// Note that, due to the buddy allocation algorithm used, the available bytes may
/// not be able to allocate all at once.
fn available_bytes()