.
This commit is contained in:
parent
95d74c2ef4
commit
a66e58193f
25 changed files with 2600 additions and 93 deletions
136
arena.c
136
arena.c
|
|
@ -1,8 +1,11 @@
|
|||
#include "arena.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#if COLLA_DEBUG
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "os.h"
|
||||
|
||||
static uptr arena__align(uptr ptr, usize align) {
|
||||
|
|
@ -25,12 +28,18 @@ arena_t malloc_arena = {
|
|||
|
||||
arena_t arena_init(const arena_desc_t *desc) {
|
||||
arena_t out = {0};
|
||||
|
||||
#if COLLA_DEBUG
|
||||
out.file = desc->file;
|
||||
out.line = desc->line;
|
||||
#endif
|
||||
|
||||
if (desc) {
|
||||
switch (desc->type) {
|
||||
case ARENA_VIRTUAL: out = arena__make_virtual(desc->size); break;
|
||||
case ARENA_MALLOC: out = arena__make_malloc(desc->size); break;
|
||||
case ARENA_STATIC: out = arena__make_static(desc->static_buffer, desc->size); break;
|
||||
case ARENA_VIRTUAL: out = arena__make_virtual(desc->size); break;
|
||||
case ARENA_MALLOC: out = arena__make_malloc(desc->size); break;
|
||||
case ARENA_STATIC: out = arena__make_static(desc->static_buffer, desc->size); break;
|
||||
case ARENA_MALLOC_ALWAYS: out = malloc_arena; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +85,10 @@ void *arena_alloc(const arena_alloc_desc_t *desc) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (!ptr && desc->flags & ALLOC_SOFT_FAIL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
usize total = desc->size * desc->count;
|
||||
|
||||
return desc->flags & ALLOC_NOZERO ? ptr : memset(ptr, 0, total);
|
||||
|
|
@ -98,7 +111,7 @@ void arena_rewind(arena_t *arena, usize from_start) {
|
|||
return;
|
||||
}
|
||||
|
||||
assert(arena_tell(arena) >= from_start);
|
||||
colla_assert(arena_tell(arena) >= from_start);
|
||||
|
||||
arena->cur = arena->beg + from_start;
|
||||
}
|
||||
|
|
@ -137,17 +150,13 @@ static void arena__free_virtual(arena_t *arena) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool success = os_release(arena->beg, arena_capacity(arena));
|
||||
assert(success && "Failed arena free");
|
||||
os_release(arena->beg, arena_capacity(arena));
|
||||
}
|
||||
// == MALLOC ARENA =====================================================================================================
|
||||
|
||||
extern void *malloc(usize size);
|
||||
extern void free(void *ptr);
|
||||
|
||||
static arena_t arena__make_malloc(usize size) {
|
||||
u8 *ptr = malloc(size);
|
||||
assert(ptr);
|
||||
u8 *ptr = os_alloc(size);
|
||||
colla_assert(ptr);
|
||||
return (arena_t) {
|
||||
.beg = ptr,
|
||||
.cur = ptr,
|
||||
|
|
@ -157,7 +166,7 @@ static arena_t arena__make_malloc(usize size) {
|
|||
}
|
||||
|
||||
static void arena__free_malloc(arena_t *arena) {
|
||||
free(arena->beg);
|
||||
os_free(arena->beg);
|
||||
}
|
||||
|
||||
// == ARENA ALLOC ======================================================================================================
|
||||
|
|
@ -171,7 +180,10 @@ static void *arena__alloc_common(const arena_alloc_desc_t *desc) {
|
|||
|
||||
if (total > arena_remaining(arena)) {
|
||||
if (!soft_fail) {
|
||||
fatal("finished space in arena, tried to allocate %_$$$dB out of %_$$$dB\n", total, arena_remaining(arena));
|
||||
#if COLLA_DEBUG
|
||||
arena__print_crash(arena);
|
||||
#endif
|
||||
fatal("finished space in arena, tried to allocate %_$$$dB out of %_$$$dB (total: %_$$$dB)\n", total, arena_remaining(arena), (usize)(arena->end - arena->beg));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -187,10 +199,13 @@ static void *arena__alloc_common(const arena_alloc_desc_t *desc) {
|
|||
// TODO is this really correct?
|
||||
usize num_of_pages = (extra_mem / page_size) + 1;
|
||||
|
||||
assert(num_of_pages > 0);
|
||||
colla_assert(num_of_pages > 0);
|
||||
|
||||
if (!os_commit(arena->cur, num_of_pages + 1)) {
|
||||
if (!soft_fail) {
|
||||
#if COLLA_DEBUG
|
||||
arena__print_crash(arena);
|
||||
#endif
|
||||
fatal("failed to commit memory for virtual arena, tried to commit %zu pages\n", num_of_pages);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -201,6 +216,14 @@ static void *arena__alloc_common(const arena_alloc_desc_t *desc) {
|
|||
u8 *ptr = arena->cur;
|
||||
arena->cur += total;
|
||||
|
||||
#if COLLA_DEBUG
|
||||
alloc_header_t *header = calloc(1, sizeof(alloc_header_t));
|
||||
header->size = desc->size;
|
||||
header->count = desc->count;
|
||||
memcpy(header->type_name, desc->type_name.buf, MIN(desc->type_name.len, sizeof(header->type_name)));
|
||||
list_push(arena->head, header);
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -208,9 +231,9 @@ static void *arena__alloc_malloc_always(const arena_alloc_desc_t *desc) {
|
|||
usize total = desc->size * desc->count;
|
||||
|
||||
// TODO: alignment?
|
||||
u8 *ptr = malloc(total);
|
||||
u8 *ptr = os_alloc(total);
|
||||
if (!ptr && !(desc->flags & ALLOC_SOFT_FAIL)) {
|
||||
fatal("malloc call failed for %_$$$dB", total);
|
||||
fatal("alloc call failed for %_$$$dB", total);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
|
@ -228,3 +251,82 @@ static arena_t arena__make_static(u8 *buf, usize len) {
|
|||
};
|
||||
}
|
||||
|
||||
// == DEBUG ============================================================================================================
|
||||
#if COLLA_DEBUG
|
||||
|
||||
#define ARENA_HMAP_SIZE (1024)
|
||||
|
||||
typedef struct arena_hnode_t arena_hnode_t;
|
||||
struct arena_hnode_t {
|
||||
u32 size;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
typedef struct arena_hmap_t arena_hmap_t;
|
||||
struct arena_hmap_t {
|
||||
u64 hashes[ARENA_HMAP_SIZE];
|
||||
char keys[ARENA_HMAP_SIZE][16];
|
||||
arena_hnode_t values[ARENA_HMAP_SIZE];
|
||||
};
|
||||
|
||||
u64 arena_hmap_hash(char key[16]) {
|
||||
const u8 *data = (const u8 *)key;
|
||||
u64 hash = 0;
|
||||
|
||||
for (usize i = 0; i < 16; ++i) {
|
||||
hash = data[i] + (hash << 6) + (hash << 16) - hash;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
arena_hnode_t *arena_hmap_find_or_add(arena_hmap_t *map, char key[16]) {
|
||||
u64 hash = arena_hmap_hash(key);
|
||||
usize index = hash & (ARENA_HMAP_SIZE - 1);
|
||||
|
||||
usize beg = index;
|
||||
usize end = ARENA_HMAP_SIZE;
|
||||
|
||||
for (usize k = 0; k < 2; ++k) {
|
||||
for (usize i = index; i < ARENA_HMAP_SIZE; ++i) {
|
||||
if (map->hashes[i] == 0){
|
||||
arena_hnode_t *node = &map->values[i];
|
||||
map->hashes[i] = hash;
|
||||
memcpy(map->keys[i], key, 16);
|
||||
return node;
|
||||
}
|
||||
|
||||
if (map->hashes[i] == hash && memcmp(map->keys[i], key, 16) == 0) {
|
||||
return &map->values[i];
|
||||
}
|
||||
}
|
||||
|
||||
beg = 0;
|
||||
end = index;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void arena__print_crash(arena_t *arena) {
|
||||
arena_hmap_t hmap = {0};
|
||||
|
||||
debug("arena %v:%d", arena->file, arena->line);
|
||||
|
||||
for_each (header, arena->head) {
|
||||
arena_hnode_t *node = arena_hmap_find_or_add(&hmap, header->type_name);
|
||||
colla_assert(node->size == 0 || node->size == header->size);
|
||||
node->size = header->size;
|
||||
node->count += header->count;
|
||||
}
|
||||
|
||||
print("type name | size\t| count\t| total\n");
|
||||
for (usize i = 0; i < ARENA_HMAP_SIZE; ++i) {
|
||||
if (hmap.hashes[i] == 0) continue;
|
||||
arena_hnode_t n = hmap.values[i];
|
||||
print("%16s| %_$$$dB\t| %d\t| %_$$$dB\n", hmap.keys[i], n.size, n.count, n.size * n.count);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue