added freearena(..) because it was really needed - untested, but probably good

This commit is contained in:
Richard Thier 2024-10-22 11:49:03 +02:00
parent 3037bf6bec
commit dfff5028f3

100
arena.h
View File

@ -16,88 +16,98 @@
static void *os_reserve(ptrdiff_t); static void *os_reserve(ptrdiff_t);
static char os_commit(void *, ptrdiff_t); static char os_commit(void *, ptrdiff_t);
static char os_free(void *, ptrdiff_t);
#define ARENA_PAGESIZE ((ptrdiff_t)1<<26) #define ARENA_PAGESIZE ((ptrdiff_t)1<<26)
typedef struct { typedef struct {
char *begin; char *begin;
char *commit; char *commit;
char *end; char *end;
} arena; } arena;
static arena newarena(ptrdiff_t cap) static inline arena newarena(ptrdiff_t cap) {
{ arena a = {0};
arena a = {0}; cap += -cap & (ARENA_PAGESIZE - 1);
cap += -cap & (ARENA_PAGESIZE - 1); a.begin = a.commit = a.end = (char*) os_reserve(cap);
a.begin = a.commit = a.end = (char*) os_reserve(cap); if (a.begin) {
if (a.begin) { a.end += cap;
a.end += cap; }
} return a;
return a;
} }
static void *aralloc(arena *a, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count) 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 padding = -(size_t)a->begin & (align - 1); ptrdiff_t committed = a->commit - a->begin;
ptrdiff_t committed = a->commit - a->begin; if (count > (committed-padding)/size) {
if (count > (committed-padding)/size) { ptrdiff_t reserved = a->end - a->begin;
ptrdiff_t reserved = a->end - a->begin; if (count > (reserved-padding)/size) {
if (count > (reserved-padding)/size) { return 0;
return 0; }
}
ptrdiff_t needed = size*count + padding - committed; ptrdiff_t needed = size*count + padding - committed;
needed += -needed & (ARENA_PAGESIZE - 1); needed += -needed & (ARENA_PAGESIZE - 1);
if (!os_commit(a->commit, needed)) { if (!os_commit(a->commit, needed)) {
return 0; return 0;
} }
a->commit += needed; a->commit += needed;
} }
void *ptr = a->begin + padding; void *ptr = a->begin + padding;
a->begin += padding + size*count; a->begin += padding + size*count;
// Change to this instead if you want zero-inited (but this gets slow with many arenas) // 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; return ptr;
} }
/** Removes an arena (fully) */
static inline char freearena(arena *a) {
return os_free(a->begin, (a->end) - (a->begin));
}
#ifdef _WIN32 #ifdef _WIN32
// $ cc -g3 -nostartfiles -o arena.exe arena.c // $ cc -g3 -nostartfiles -o arena.exe arena.c
// $ cl /Z7 arena.c /link /subsystem:console kernel32.lib libvcruntime.lib // $ cl /Z7 arena.c /link /subsystem:console kernel32.lib libvcruntime.lib
#define W32(r) __declspec(dllimport) r __stdcall #define W32(r) __declspec(dllimport) r __stdcall
W32(void) ExitProcess(int); W32(void) ExitProcess(int);
W32(void *) VirtualAlloc(void *, ptrdiff_t, int, int); W32(void *) VirtualAlloc(void *, ptrdiff_t, int, int);
W32(void *) VirtualFree(void *, ptrdiff_t, int);
#define MEM_COMMIT 0x1000 #define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000 #define MEM_RESERVE 0x2000
#define PAGE_NOACCESS 0x0001 #define PAGE_NOACCESS 0x0001
#define PAGE_READWRITE 0x0004 #define PAGE_READWRITE 0x0004
#define MEM_RELEASE 0x8000
static void *os_reserve(ptrdiff_t cap) static void *os_reserve(ptrdiff_t cap) {
{ return VirtualAlloc(0, cap, MEM_RESERVE, PAGE_NOACCESS);
return VirtualAlloc(0, cap, MEM_RESERVE, PAGE_NOACCESS);
} }
static char os_commit(void *ptr, ptrdiff_t len) static char os_commit(void *ptr, ptrdiff_t len) {
{ return VirtualAlloc(ptr, len, MEM_COMMIT, PAGE_READWRITE);
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 #else // POSIX
// $ cc -g3 -o arena arena.c
#include <sys/mman.h> #include <sys/mman.h>
static void *os_reserve(ptrdiff_t cap) static void *os_reserve(ptrdiff_t cap) {
{ void *r = mmap(0, cap, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
void *r = mmap(0, cap, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); return r==MAP_FAILED ? 0 : r;
return r==MAP_FAILED ? 0 : r;
} }
static char os_commit(void *ptr, ptrdiff_t len) static char os_commit(void *ptr, ptrdiff_t len) {
{ return !mprotect(ptr, len, PROT_READ|PROT_WRITE);
return !mprotect(ptr, len, PROT_READ|PROT_WRITE);
} }
static char os_free(void *ptr, ptrdiff_t len) {
return !munmap(ptr, len);
}
#endif // POSIX #endif // POSIX
#endif /* ARENA_H */ #endif /* ARENA_H */