Expand description
BuddyPool implements a simple buddy-system allocator. It does not assume that the memory (or resource) being allocated is accessible, and uses only its own data structures for metadata. It thus can be used, for example to allocate I/O memory that is not directly accessible to the CPU. As part of this approach, BuddyPool does not contain any unsafe code, using Vec structures with integers for linking lists. This approach does consume more memory than some other approaches.
§Types
- BuddyPool
- This struct is the type for a memory pool.
- BuddyConfig
- This struct is used to pass configuration parameters to the pool constructor.
- BuddyStats
- The pool implementation keeps some statistics on operations. This struct is used to return them to the user.
- BuddyError
- Pool functions use this type to return information on errors.
- Index
- The allocator uses this type for indices. Types u8, u16, u32, and usize have been tested. Smaller types will limit the maximum pool size, but save on overhead.
§Example
use buddy_pool::BuddyPool;
use buddy_pool::BuddyConfig;
use buddy_pool::BuddyErrorType;
use std::alloc::alloc;
use std::alloc::Layout;
// Allocate some memory for testing.
let bytes: usize = 2 * 1024 * 1024;
let alloc_mem =
unsafe {
alloc(Layout::array::<u8>(bytes).unwrap())
} as usize;
// Get the configuration parameters ready.
let config =
BuddyConfig {
base: alloc_mem , // the base address from libc::malloc
size: bytes, // the size of the memory region in bytes
min_alloc: 1, // the minimum allocation size allowed
max_alloc: 17 * 1024, // the largest allocation that will be allowed
min_buddy: 8192, // the minimum size buddy block that will be created
};
// Construct the pool and try an alloc/free pair.
let mut pool = BuddyPool::new(config).unwrap();
let address = pool.alloc(config.max_alloc).unwrap();
assert!(address >= config.base && address < config.base + config.size);
pool.free(address).unwrap();
// Try a double free.
let result = pool.free(address);
assert!(result.is_err());
assert!(result.unwrap_err().error_type() == BuddyErrorType::FreeingFreeMemory);
// Try an undersized allocation.
let result = pool.alloc(config.min_alloc - 1);
assert!(result.is_err());
assert!(result.unwrap_err().error_type() == BuddyErrorType::UndersizeAlloc);
// Try an oversized allocation.
let result = pool.alloc(config.max_alloc + 1);
assert!(result.is_err());
assert!(result.unwrap_err().error_type() == BuddyErrorType::OversizeAlloc);
// Now allocate until the pool is empty. Keep track
// of the allocation count to see that it matches
// the configuration.
let mut allocs = 0;
loop {
let result = pool.alloc(config.min_alloc);
if result.is_err() {
let error = result.unwrap_err();
assert!(error.error_type() == BuddyErrorType::OutOfMemory);
break;
}
allocs += 1;
}
assert!(allocs == config.size / config.min_buddy);Structs§
- Buddy
Config - Specifies the configuration parameters for a pool.
- Buddy
Error - Contains the error information for failed requests.
- Buddy
Pool - Defines the pool type itself.
- Buddy
Stats - Contains the results of a query for statistics on the pool.
- List
Stats - Contains the statistics returned by a single list. Currently, the only lists are the free lists.
Enums§
- Buddy
Error Type - Defines the error codes for all operations.
Functions§
- compute_
buddy_ size - Converts a byte count into a buddy size, if possibe, obeying the limits on buddy sizes given as parameters.
Type Aliases§
- Index
- This type can be set to u8, u16, u32, or usize, as needed to match the pool size. The size limit of a pool in bytes is usize::MAX / 2 or (Index::MAX + 1) * min_size, whichever is smaller. For example, a min_size parameter of 1024 bytes using u32 indices sets a limit of 4 terabytes per memory pool.