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

36
arena.h
View File

@ -16,6 +16,7 @@
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)
@ -25,8 +26,7 @@ typedef struct {
char *end;
} arena;
static arena newarena(ptrdiff_t cap)
{
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);
@ -36,8 +36,7 @@ static arena newarena(ptrdiff_t cap)
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 committed = a->commit - a->begin;
if (count > (committed-padding)/size) {
@ -62,42 +61,53 @@ static void *aralloc(arena *a, ptrdiff_t size, ptrdiff_t align, ptrdiff_t 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)
{
static void *os_reserve(ptrdiff_t cap) {
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);
}
static char os_free(void *ptr, ptrdiff_t len) {
return VirtualFree(ptr, len, MEM_RELEASE);
}
#else // POSIX
// $ cc -g3 -o arena arena.c
#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);
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);
}
static char os_free(void *ptr, ptrdiff_t len) {
return !munmap(ptr, len);
}
#endif // POSIX
#endif /* ARENA_H */