Skip to content

nic-obert/buddy-allocator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Buddy Allocator

A buddy allocator implemented in Rust.

Basic usage

Allocate and free memory:

// Create a buddy allocator with a heap size of 1024 bytes and a zero-order block of 8 bytes.
let mut alloc = BuddyAllocator::<1024, 8>::new(false);

let size_to_alloc: usize = 16;

// Allocate a memory block.
let my_pointer: NonNull<u8> = alloc.as_mut().alloc_bytes(size_to_alloc).unwrap_or_else(
    |err| panic!("Allocation failed with error {:?}", err)
);

// Do stuff with the pointer...

// Free the memory block
alloc.as_mut().free_nonnull(my_pointer).unwrap_or_else(
    |err| panic!("Failed to free pointer {:?} with error {:?}", my_pointer, err)
); 

Allocate memory for a structure:

// Create a buddy allocator with a heap size of 1024 bytes and a zero-order block of 8 bytes.
let mut alloc = BuddyAllocator::<1024, 8>::new(false);

struct MyStruct (usize, usize, u32);

// Allocate a memory block that fits an instance of MyStruct.
let my_ptr = alloc.as_mut().alloc::<MyStruct>()
    .unwrap_or_else(|err| panic!("Allocation failed with error {:?}", err));

// You can also cast the NonNull<T> to a raw pointer.
let my_ptr = my_ptr.as_ptr();

// Initialize the struct.
unsafe {
    *my_ptr = MyStruct (32, 3, 90);
}

// Free the block that contains the struct.
alloc.as_mut().free(my_ptr)
    .unwrap_or_else(|err| panic!("Failed to free pointer {:?} with error {:?}", my_ptr, err)
);

Construct the allocator directly on the stack. This approach removes any dependency on the standard system allocator, which is suitable for embedded development or in #![no_std] environments where an allocator may not be avalilable.

// Create a buddy allocator with a heap size of 1024 bytes and a zero-order block of 8 bytes.
// The allocator must be readily pinned because it will live on the stack.
let mut alloc = pin!( unsafe { 
    BuddyAllocator::<1024, 8>::new_unpinned(false)
});
// Initializing a stack-pinned allocator is mandatory to use it safely
unsafe {
    alloc.as_mut().init_pinned()
}

let size_to_alloc: usize = 16;

// Allocate a memory block.
let my_pointer: NonNull<u8> = alloc.as_mut().alloc_bytes(size_to_alloc).unwrap_or_else(
    |err| panic!("Allocation failed with error {:?}", err)
);

// Do stuff with the pointer...

// Free the memory block
alloc.as_mut().free_nonnull(my_pointer).unwrap_or_else(
    |err| panic!("Failed to free pointer {:?} with error {:?}", my_pointer, err)
); 


// Also works with structs

struct MyStruct (usize, usize, u32);

// Allocate a memory block that fits an instance of MyStruct.
let my_ptr = alloc.as_mut().alloc::<MyStruct>()
    .unwrap_or_else(|err| panic!("Allocation failed with error {:?}", err));

// You can also cast the NonNull<T> to a raw pointer.
let my_ptr = my_ptr.as_ptr();

// Initialize the struct.
unsafe {
    *my_ptr = MyStruct (32, 3, 90);
}

// Free the block that contains the struct.
alloc.as_mut().free(my_ptr)
    .unwrap_or_else(|err| panic!("Failed to free pointer {:?} with error {:?}", my_ptr, err)
);

How it works

This buddy allocator implementation keeps a record of the allocated and free blocks using a binary tree, where each leaf node represents a memory block. Adjacent free nodes are merged to avoid fragmentation and big memory blocks are split in half is the requested allocation is small enough.

A more detailed explanation is available in the source code through comments.

License

This repository and the code within it are published under the MIT license.

About

A buddy allocator implemented in Rust

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published