#pragma once #include #include #define MAGIC_COOKIE_BYTES 32 #define ADDRESS_BITS (8 * sizeof(void*)) struct buddy { uint8_t magic[MAGIC_COOKIE_BYTES]; struct free_block *(avail[ADDRESS_BITS]); size_t root_logsize; void *base; }; // Initialize a buddy with (constant) global state stored in @state. // NOTE: after initializing the buddy, you should always pass the exact same // pointer in for @state in future calls. If you need to move @state, use // move_buddy(...). void init_buddy(uint8_t *base, size_t size, uint8_t magic[MAGIC_COOKIE_BYTES], struct buddy *state); // Allocate a block of size >= @size void *allocate(size_t size, struct buddy *state); // Liberate a block of size @size starting at @base. void liberate(void *base, size_t size, struct buddy *state); // Print debug information for the allocator. void debug_buddy(struct buddy *state); // Simulates @new = allocate, memcpy(@new, @old), free(@old), with some // optimizations for cases where the reallocation can be done in place. void *reallocate(void *old, size_t old_size, size_t new_size, struct buddy *state); // Attempts to reserve a range [@start,@start+@size). // Returns 1 if success, 0 otherwise. // Whenever possible, we avoid writing anything into the reserved region. int reserve(void *start, size_t size, struct buddy *state); // Update @state to assume the memory pool has been copied to // [@new_base,@new_base+@new_size) // Can *ONLY* be used when @new_size >= the existing size. void grow_buddy(uint8_t *new_base, size_t new_size, struct buddy *state); // Update @state to only use the subset of the pool in range // [@state->base,@state->base+new_size) // Can *ONLY* be used when @new_size <= the existing size. // This *CAN* write to anything in the old pool. // This *CAN* fail, in which case everything is unmodified and 0 is returned. // Upon success, 1 is returned. int shrink_buddy(size_t new_size, struct buddy *state); // Used to move the global state of the buddy. void move_buddy(struct buddy *new_state, struct buddy *old_state);