Reimplement the arena

This commit is contained in:
kamkow1
2025-06-01 01:47:47 +02:00
parent a191abc2b7
commit 3636b08c10
2 changed files with 49 additions and 98 deletions

View File

@ -9,13 +9,13 @@ typedef struct {
int main(void) int main(void)
{ {
Arena *arena = arena_make(sizeof(int)); Arena arena = gebs_arena_get(4*1024);
defer { arena_destroy(arena); } defer { arena_destroy(&arena); }
Ints ints = {0}; Ints ints = {0};
defer { list_free_alloc(arena, &ints); } for (size_t i = 0; i < 100; i++) {
for (size_t i = 0; i < 1000; i++) { list_append_alloc(&arena, &ints, i);
list_append_alloc(arena, &ints, i); gebs_arena_reset(&arena);
} }
for (size_t i = 0; i < ints.count; i++) { for (size_t i = 0; i < ints.count; i++) {
printf("%zu\n", i); printf("%zu\n", i);

137
gebs.h
View File

@ -33,6 +33,7 @@
# include <sys/stat.h> # include <sys/stat.h>
# include <sys/types.h> # include <sys/types.h>
# include <sys/wait.h> # include <sys/wait.h>
# include <sys/mman.h>
#else #else
# error "Unknown GEBS_PLATFORM" # error "Unknown GEBS_PLATFORM"
#endif #endif
@ -96,31 +97,32 @@ void gebs_default_allocator_free(void *self, void *memory);
void *gebs_default_allocator_realloc(void *self, void *memory, void *gebs_default_allocator_realloc(void *self, void *memory,
size_t prev_size, size_t new_size); size_t prev_size, size_t new_size);
typedef struct Gebs_Arena_Allocation {
size_t index;
size_t size;
char *ptr;
struct Gebs_Arena_Allocation *next;
} Gebs_Arena_Allocation;
typedef struct { typedef struct {
void *(*malloc)(void *self, size_t size); void *(*malloc)(void *self, size_t size);
void (*free)(void *self, void *memory); void (*free)(void *self, void *memory);
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size); void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
char *region; void *buffer;
size_t index; void *end;
size_t size; size_t capacity;
} Gebs_Arena; } Gebs_Arena;
void gebs_arena_reset(Gebs_Arena *a); void gebs_arena_reset(Gebs_Arena *a);
void gebs_arena_destroy(Gebs_Arena *a); void gebs_arena_destroy(Gebs_Arena *a);
Gebs_Arena *gebs_arena_make(size_t size);
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size);
void *gebs_arena_malloc(void *self, size_t size); void *gebs_arena_malloc(void *self, size_t size);
void gebs_arena_free(void *self, void *memory); void gebs_arena_free(void *self, void *memory);
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size); void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size);
#define gebs_arena_get(cap) \
({ \
Gebs_Arena __arena = {0}; \
__arena.malloc = &gebs_arena_malloc; \
__arena.realloc = &gebs_arena_realloc; \
__arena.free = &gebs_arena_free; \
__arena.capacity = (cap); \
__arena; \
})
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Dynamic list // Dynamic list
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -301,7 +303,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
# define GEBS_SCRATCH_ARENA_SIZE 4096 # define GEBS_SCRATCH_ARENA_SIZE 4096
#endif #endif
extern Gebs_Arena *gebs_scratch_arena; extern Gebs_Arena gebs_scratch_arena;
char *gebs_fmt(const char *fmt, ...); char *gebs_fmt(const char *fmt, ...);
void gebs_scratch_arena_reset(void); void gebs_scratch_arena_reset(void);
@ -316,6 +318,7 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
{ {
Gebs_String_Builder sb = {0}; Gebs_String_Builder sb = {0};
gebs_nsl_join_alloc(alloc, cmd, &sb, " "); gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items); GEBS_LOGI("cmd `%s`\n", sb.items);
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX #if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
@ -363,6 +366,7 @@ int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_S
{ {
Gebs_String_Builder sb = {0}; Gebs_String_Builder sb = {0};
gebs_nsl_join_alloc(alloc, cmd, &sb, " "); gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items); GEBS_LOGI("cmd `%s`\n", sb.items);
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX #if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
@ -449,68 +453,23 @@ void *gebs_default_allocator_realloc(discard void *self, void *memory,
return p; return p;
} }
Gebs_Arena *gebs_arena_make(size_t size)
{
Gebs_Arena *a;
if (size == 0) {
return NULL;
}
a = malloc(sizeof(*a));
if (a == NULL) {
return NULL;
}
a->malloc = &gebs_arena_malloc;
a->free = &gebs_arena_free;
a->realloc = &gebs_arena_realloc;
a->region = malloc(size);
if (a->region == NULL) {
free(a);
return NULL;
}
a->index = 0;
a->size = size;
return a;
}
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size)
{
if (a == NULL || new_size <= a->size) {
return NULL;
}
a->region = realloc(a->region, new_size);
if (a->region == NULL) {
return NULL;
}
a->size = new_size;
return a;
}
void *gebs_arena_malloc(void *self, size_t size) void *gebs_arena_malloc(void *self, size_t size)
{ {
Gebs_Arena *a = (Gebs_Arena *)self; Gebs_Arena *a = (Gebs_Arena *)self;
unsigned int offset;
if (size == 0) { if (a->buffer == NULL) {
return NULL; #if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
int prot = PROT_READ | PROT_WRITE;
int vis = MAP_SHARED | MAP_ANONYMOUS;
a->buffer = mmap(0, a->capacity, prot, vis, -1, 0);
#else
# error "gebs_arena_malloc unknown platform"
#endif
a->end = a->buffer;
} }
void *p = a->end;
if (a == NULL || a->region == NULL) { a->end = (void *)((uintptr_t)a->end + size);
return NULL; return p;
}
offset = 0;
if (a->size - (a->index + offset) < size) {
return NULL;
}
a->index += size;
return a->region + (a->index - size);
} }
void gebs_arena_free(discard void *self, discard void *memory) void gebs_arena_free(discard void *self, discard void *memory)
@ -518,53 +477,45 @@ void gebs_arena_free(discard void *self, discard void *memory)
} }
void *gebs_arena_realloc(void *self, void *memory, void *gebs_arena_realloc(void *self, void *memory,
discard size_t prev_size, size_t new_size) size_t prev_size, size_t new_size)
{ {
Gebs_Arena *a = (Gebs_Arena *)self; Gebs_Arena *a = (Gebs_Arena *)self;
uintptr_t offset = (char *)memory - a->region; void *new = gebs_arena_malloc(a, new_size);
gebs_arena_expand(a, a->size + new_size); memcpy(new, memory, prev_size);
return a->region + offset; return new;
} }
void gebs_arena_reset(Gebs_Arena *a) void gebs_arena_reset(Gebs_Arena *a)
{ {
if (a == NULL) { a->end = a->buffer;
return;
}
a->index = 0;
} }
void gebs_arena_destroy(Gebs_Arena *a) void gebs_arena_destroy(Gebs_Arena *a)
{ {
if (a == NULL) { #if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
return; munmap(a->buffer, a->capacity);
} #else
# error "gebs_arena_destroy unknown platform"
if (a->region != NULL) { #endif
free(a->region);
}
free(a);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Scratch arena // Scratch arena
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
Gebs_Arena *gebs_scratch_arena; Gebs_Arena gebs_scratch_arena;
__attribute__((constructor)) __attribute__((constructor))
void gebs_scratch_areana_init(void) void gebs_scratch_areana_init(void)
{ {
gebs_scratch_arena = gebs_arena_make(GEBS_SCRATCH_ARENA_SIZE); gebs_scratch_arena = gebs_arena_get(4*1024);
} }
__attribute__((destructor)) __attribute__((destructor))
void gebs_scratch_areana_free(void) void gebs_scratch_areana_free(void)
{ {
gebs_arena_destroy(gebs_scratch_arena); gebs_arena_destroy(&gebs_scratch_arena);
} }
char *gebs_fmt(const char *fmt, ...) char *gebs_fmt(const char *fmt, ...)
@ -577,7 +528,7 @@ char *gebs_fmt(const char *fmt, ...)
size_t size = vsnprintf(NULL, 0, fmt, list_copy); size_t size = vsnprintf(NULL, 0, fmt, list_copy);
va_end(list_copy); va_end(list_copy);
char *buf = gebs_malloc(gebs_scratch_arena, size+1); char *buf = gebs_malloc(&gebs_scratch_arena, size+1);
vsprintf(buf, fmt, list); vsprintf(buf, fmt, list);
va_end(list); va_end(list);
return buf; return buf;
@ -585,7 +536,7 @@ char *gebs_fmt(const char *fmt, ...)
void gebs_scratch_arena_reset(void) void gebs_scratch_arena_reset(void)
{ {
gebs_arena_reset(gebs_scratch_arena); gebs_arena_reset(&gebs_scratch_arena);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------