added freearena(..) because it was really needed - untested, but probably good
This commit is contained in:
parent
3037bf6bec
commit
dfff5028f3
100
arena.h
100
arena.h
@ -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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user