From dfff5028f3f7baee4e764744a656baf553bc4b70 Mon Sep 17 00:00:00 2001 From: Richard Thier Date: Tue, 22 Oct 2024 11:49:03 +0200 Subject: [PATCH] added freearena(..) because it was really needed - untested, but probably good --- arena.h | 100 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/arena.h b/arena.h index ecafbda..d824b63 100644 --- a/arena.h +++ b/arena.h @@ -16,88 +16,98 @@ static void *os_reserve(ptrdiff_t); static char os_commit(void *, ptrdiff_t); +static char os_free(void *, ptrdiff_t); #define ARENA_PAGESIZE ((ptrdiff_t)1<<26) typedef struct { - char *begin; - char *commit; - char *end; + char *begin; + char *commit; + char *end; } arena; -static arena newarena(ptrdiff_t cap) -{ - arena a = {0}; - cap += -cap & (ARENA_PAGESIZE - 1); - a.begin = a.commit = a.end = (char*) os_reserve(cap); - if (a.begin) { - a.end += cap; - } - return a; +static inline arena newarena(ptrdiff_t cap) { + arena a = {0}; + cap += -cap & (ARENA_PAGESIZE - 1); + a.begin = a.commit = a.end = (char*) os_reserve(cap); + if (a.begin) { + a.end += cap; + } + return a; } -static void *aralloc(arena *a, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count) -{ - ptrdiff_t padding = -(size_t)a->begin & (align - 1); - ptrdiff_t committed = a->commit - a->begin; - if (count > (committed-padding)/size) { - ptrdiff_t reserved = a->end - a->begin; - if (count > (reserved-padding)/size) { - return 0; - } +static inline void *aralloc(arena *a, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count) { + ptrdiff_t padding = -(size_t)a->begin & (align - 1); + ptrdiff_t committed = a->commit - a->begin; + if (count > (committed-padding)/size) { + ptrdiff_t reserved = a->end - a->begin; + if (count > (reserved-padding)/size) { + return 0; + } - ptrdiff_t needed = size*count + padding - committed; - needed += -needed & (ARENA_PAGESIZE - 1); - if (!os_commit(a->commit, needed)) { - return 0; - } - a->commit += needed; - } + ptrdiff_t needed = size*count + padding - committed; + needed += -needed & (ARENA_PAGESIZE - 1); + if (!os_commit(a->commit, needed)) { + return 0; + } + a->commit += needed; + } - void *ptr = a->begin + padding; - a->begin += padding + size*count; + void *ptr = a->begin + padding; + a->begin += padding + size*count; // Change to this instead if you want zero-inited (but this gets slow with many arenas) - //return memset(ptr, 0, size*count); + //return memset(ptr, 0, size*count); return ptr; } +/** Removes an arena (fully) */ +static inline char freearena(arena *a) { + return os_free(a->begin, (a->end) - (a->begin)); +} + #ifdef _WIN32 // $ cc -g3 -nostartfiles -o arena.exe arena.c // $ cl /Z7 arena.c /link /subsystem:console kernel32.lib libvcruntime.lib #define W32(r) __declspec(dllimport) r __stdcall W32(void) ExitProcess(int); W32(void *) VirtualAlloc(void *, ptrdiff_t, int, int); +W32(void *) VirtualFree(void *, ptrdiff_t, int); #define MEM_COMMIT 0x1000 #define MEM_RESERVE 0x2000 #define PAGE_NOACCESS 0x0001 #define PAGE_READWRITE 0x0004 +#define MEM_RELEASE 0x8000 -static void *os_reserve(ptrdiff_t cap) -{ - return VirtualAlloc(0, cap, MEM_RESERVE, PAGE_NOACCESS); +static void *os_reserve(ptrdiff_t cap) { + return VirtualAlloc(0, cap, MEM_RESERVE, PAGE_NOACCESS); } -static char os_commit(void *ptr, ptrdiff_t len) -{ - return VirtualAlloc(ptr, len, MEM_COMMIT, PAGE_READWRITE); +static char os_commit(void *ptr, ptrdiff_t len) { + return VirtualAlloc(ptr, len, MEM_COMMIT, PAGE_READWRITE); +} + +static char os_free(void *ptr, ptrdiff_t len) { + return VirtualFree(ptr, len, MEM_RELEASE); } #else // POSIX -// $ cc -g3 -o arena arena.c #include -static void *os_reserve(ptrdiff_t cap) -{ - void *r = mmap(0, cap, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); - return r==MAP_FAILED ? 0 : r; +static void *os_reserve(ptrdiff_t cap) { + void *r = mmap(0, cap, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); + return r==MAP_FAILED ? 0 : r; } -static char os_commit(void *ptr, ptrdiff_t len) -{ - return !mprotect(ptr, len, PROT_READ|PROT_WRITE); +static char os_commit(void *ptr, ptrdiff_t len) { + return !mprotect(ptr, len, PROT_READ|PROT_WRITE); } + +static char os_free(void *ptr, ptrdiff_t len) { + return !munmap(ptr, len); +} + #endif // POSIX #endif /* ARENA_H */