#ifndef ARENA_IMPL #define ARENA_IMPL #include #include #include #include #include #include #include #include #define PAGESIZE 4096 #ifndef ARENA_MEMORY #define ARENA_MEMORY PAGESIZE #endif typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; typedef int8_t s8; typedef int16_t s16; typedef int32_t s32; typedef int64_t s64; struct Arena { void *memory; u64 size; u64 pos; } typedef Arena; // Create an arena Arena *ArenaAlloc(void); // Destroy an arena void ArenaRelease(Arena *arena); // Push bytes on to the arena | allocating void *ArenaPush(Arena *arena, u64 size); void *ArenaPushZero(Arena *arena, u64 size); #define PushArray(arena, type, count) (type *)ArenaPush((arena), sizeof(type) * (count)) #define PushArrayZero(arena, type, count) (type *)ArenaPushZero((arena), sizeof(type) * (count)) #define PushStruct(arena, type) PushArray((arena), (type), 1) #define PushStructZero(arena, type) PushArrayZero((arena), (type), 1) // Free some bytes by popping the stack void ArenaPop(Arena *arena, u64 size); // Get the number of bytes allocated u64 ArenaGetPos(Arena *arena); void ArenaSetPosBack(Arena *arena, u64 pos); void ArenaClear(Arena *arena); Arena *ArenaAlloc(void) { // NOTE: If the arena is created here the pointer to the memory get's overwritten with size in // ArenaPush, so we are forced to use malloc Arena *arena = malloc(sizeof(Arena)); arena->memory = mmap(NULL, ARENA_MEMORY, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (arena->memory == MAP_FAILED) return NULL; arena->pos = 0; arena->size = ARENA_MEMORY; return arena; } void ArenaRelease(Arena *arena) { munmap(arena->memory, ARENA_MEMORY); free(arena); } void *ArenaPush(Arena *arena, u64 size) { u64 *mem; mem = (u64 *)arena->memory + arena->pos; arena->pos += size; return mem; } void *ArenaPushZero(Arena *arena, u64 size) { u64 *mem; mem = (u64 *)arena->memory + arena->pos; bzero(mem, size); arena->pos += size; return mem; } void ArenaPop(Arena *arena, u64 size) { arena->pos -= size; } u64 ArenaGetPos(Arena *arena) { return arena->pos; } void ArenaSetPosBack(Arena *arena, u64 pos) { arena->pos -= pos; } void ArenaClear(Arena *arena) { bzero(arena->memory, arena->size); arena->pos = 0; } #endif