#include "arena_allocator.h" #include #include /* memset */ #include /* sysconf */ #include /* madvise */ #define MEMORY_ALIGNMENT 2*sizeof(void *) static int power_of_two(int value) { return (value & (value-1)) == 0; } static unsigned long long align_address_backward(unsigned long long address, unsigned long long alignment) { unsigned long long mod; assert(power_of_two(alignment)); mod = address & (unsigned long long)(alignment-1); if(mod != 0) address -= mod; return address; } static unsigned long long align_address_forward(unsigned long long address, unsigned long long alignment) { unsigned long long mod; assert(power_of_two(alignment)); mod = address & (unsigned long long)(alignment-1); if(mod != 0) address += alignment - mod; return address; } struct arena arena_init(void *backing_store, unsigned long long size) { struct arena result; assert(backing_store); memset(&result, 0, sizeof(result)); result.size = size; result.used = 0; result.memory = backing_store; return result; } void arena_reset(struct arena *arena) { assert(arena); arena->used = 0; } void arena_tidy(struct arena *arena) { assert(arena); unsigned long long alignment, address, offset; alignment = (unsigned long long)sysconf(_SC_PAGESIZE); address = (unsigned long long)(arena->memory + arena->used); offset = align_address_forward(address, alignment) - address; address += offset; /* TODO: Macos, FreeBSD, and Linux equivalents. */ madvise((void *)address, (size_t)(address - arena->used), MADV_DONTNEED); } void *arena_alloc(struct arena *arena, unsigned long long size) { unsigned long long address, offset; void *ret_address; assert(arena); ret_address = 0; address = (unsigned long long)(arena->memory + arena->used); offset = align_address_forward(address, MEMORY_ALIGNMENT) - address; if(arena->memory + arena->used + offset + size <= arena->memory + arena->size) { ret_address = arena->memory + arena->used + offset; memset(ret_address, 0, size); arena->used += offset + size; } return ret_address; } #define ARENA_ALLOC(a, t) (t *)arena_alloc(a, sizeof(t)) void arena_dealloc(struct arena *arena, unsigned long long size) { unsigned long long address, offset; assert(arena); address = (unsigned long long)(arena->memory + arena->used - size); offset = address - align_address_backward(address, MEMORY_ALIGNMENT); if(address >= (unsigned long long)arena->memory) arena->used -= offset + size; } #define ARENA_DEALLOC(a, t) arena_dealloc(a, sizeof(t)) struct arena temp_arena_begin(struct arena *arena) { struct arena result; assert(arena); result.size = arena->size - arena->used; result.used = 0; result.memory = arena->memory + arena->used; return result; } void temp_arena_end(struct arena *arena) { }