diff --git a/example/arena.c b/example/arena.c index 2b62c14..6d66ac7 100644 --- a/example/arena.c +++ b/example/arena.c @@ -9,13 +9,13 @@ typedef struct { int main(void) { - Arena *arena = arena_make(sizeof(int)); - defer { arena_destroy(arena); } + Arena arena = gebs_arena_get(4*1024); + defer { arena_destroy(&arena); } Ints ints = {0}; - defer { list_free_alloc(arena, &ints); } - for (size_t i = 0; i < 1000; i++) { - list_append_alloc(arena, &ints, i); + for (size_t i = 0; i < 100; i++) { + list_append_alloc(&arena, &ints, i); + gebs_arena_reset(&arena); } for (size_t i = 0; i < ints.count; i++) { printf("%zu\n", i); diff --git a/gebs.h b/gebs.h index 9c873c1..de62042 100644 --- a/gebs.h +++ b/gebs.h @@ -33,6 +33,7 @@ # include # include # include +# include #else # error "Unknown GEBS_PLATFORM" #endif @@ -96,31 +97,32 @@ void gebs_default_allocator_free(void *self, void *memory); void *gebs_default_allocator_realloc(void *self, void *memory, 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 { void *(*malloc)(void *self, size_t size); void (*free)(void *self, void *memory); void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size); - char *region; - size_t index; - size_t size; + void *buffer; + void *end; + size_t capacity; } Gebs_Arena; void gebs_arena_reset(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_free(void *self, void *memory); 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 // ---------------------------------------------------------------------------- @@ -301,7 +303,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv, # define GEBS_SCRATCH_ARENA_SIZE 4096 #endif -extern Gebs_Arena *gebs_scratch_arena; +extern Gebs_Arena gebs_scratch_arena; char *gebs_fmt(const char *fmt, ...); 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_nsl_join_alloc(alloc, cmd, &sb, " "); + gebs_sb_finish_alloc(alloc, &sb); GEBS_LOGI("cmd `%s`\n", sb.items); #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_nsl_join_alloc(alloc, cmd, &sb, " "); + gebs_sb_finish_alloc(alloc, &sb); GEBS_LOGI("cmd `%s`\n", sb.items); #if GEBS_PLATFORM == GEBS_PLATFORM_POSIX @@ -449,68 +453,23 @@ void *gebs_default_allocator_realloc(discard void *self, void *memory, 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) { Gebs_Arena *a = (Gebs_Arena *)self; - unsigned int offset; - if (size == 0) { - return NULL; + if (a->buffer == 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; } - - if (a == NULL || a->region == NULL) { - return NULL; - } - - offset = 0; - if (a->size - (a->index + offset) < size) { - return NULL; - } - - a->index += size; - return a->region + (a->index - size); + void *p = a->end; + a->end = (void *)((uintptr_t)a->end + size); + return p; } 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, - discard size_t prev_size, size_t new_size) + size_t prev_size, size_t new_size) { Gebs_Arena *a = (Gebs_Arena *)self; - uintptr_t offset = (char *)memory - a->region; - gebs_arena_expand(a, a->size + new_size); - return a->region + offset; + void *new = gebs_arena_malloc(a, new_size); + memcpy(new, memory, prev_size); + return new; } void gebs_arena_reset(Gebs_Arena *a) { - if (a == NULL) { - return; - } - - a->index = 0; + a->end = a->buffer; } void gebs_arena_destroy(Gebs_Arena *a) { - if (a == NULL) { - return; - } - - if (a->region != NULL) { - free(a->region); - } - - free(a); +#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX + munmap(a->buffer, a->capacity); +#else +# error "gebs_arena_destroy unknown platform" +#endif } // ---------------------------------------------------------------------------- // Scratch arena // ---------------------------------------------------------------------------- -Gebs_Arena *gebs_scratch_arena; +Gebs_Arena gebs_scratch_arena; __attribute__((constructor)) 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)) void gebs_scratch_areana_free(void) { - gebs_arena_destroy(gebs_scratch_arena); + gebs_arena_destroy(&gebs_scratch_arena); } 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); 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); va_end(list); return buf; @@ -585,7 +536,7 @@ char *gebs_fmt(const char *fmt, ...) void gebs_scratch_arena_reset(void) { - gebs_arena_reset(gebs_scratch_arena); + gebs_arena_reset(&gebs_scratch_arena); } // ----------------------------------------------------------------------------