Reimplement the arena
This commit is contained in:
137
gebs.h
137
gebs.h
@ -33,6 +33,7 @@
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
# include <sys/mman.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user