#include "arena.h" #include Arena * arena_init(void *mem, ptrdiff_t size) { Arena *arena = mem; arena->mem = arena + 1; arena->top = arena->mem; arena->lim = arena->mem + size; return arena; } static void * align_forward(void *ptr, ptrdiff_t align) { return (void *)(((uintptr_t)ptr + align - 1) & ~(align - 1)); } static void arena_oom(Arena *arena, ptrdiff_t size, ptrdiff_t align) { loge("Out of memory in arena %p: requested size %ld, align %ld", arena, size, align); BP(); } void * arena_alloc_aligned(Arena *arena, ptrdiff_t size, ptrdiff_t align) { uintptr_t start = (uintptr_t) align_forward(arena->top, align); if (start + size > (uintptr_t) arena->lim) { arena_oom(arena, size, align); return NULL; } memset((void *)start, 0, size); arena->top = (void *)(start + size); return (void *)start; } void * arena_realloc_aligned(Arena *arena, void *ptr, ptrdiff_t old_size, ptrdiff_t new_size, ptrdiff_t align) { if (ptr) { // check that pointer was allocated in this arena ASSERT((uintptr_t) ptr >= (uintptr_t) arena->mem); ASSERT((uintptr_t) ptr < (uintptr_t) arena->lim); ASSERT((uintptr_t) ptr + old_size <= (uintptr_t) arena->top); } void *result = NULL; if (false && ptr && (uintptr_t) ptr + old_size == (uintptr_t) arena->top) { // The block is at the top of the arena, so we can just attempt to extend it. if ((uintptr_t) ptr + new_size <= (uintptr_t) arena->lim) { // clear new memory memset((char *) ptr + old_size, 0, new_size - old_size); arena->top = ((char *) ptr + new_size); result = ptr; } else { arena_oom(arena, new_size, align); } } else { result = arena_alloc_aligned(arena, new_size, align); if (result) { if (ptr) { memcpy(result, ptr, old_size); } } else { arena_oom(arena, new_size, align); } } return result; } void arena_clear(Arena *arena) { arena_clear_overwrite(arena); arena->top = arena->mem; } void arena_clear_overwrite_with(Arena *arena, u8 value) { memset(arena->mem, value, (uintptr_t) arena->top - (uintptr_t) arena->mem); arena->top = arena->mem; } void arena_clear_overwrite(Arena *arena) { arena_clear_overwrite_with(arena, 0xCC); }