aboutsummaryrefslogtreecommitdiff
path: root/src/un_memory.c
diff options
context:
space:
mode:
authorbonmas14 <bonmas14@gmail.com>2025-09-25 14:17:07 +0300
committerbonmas14 <bonmas14@gmail.com>2025-09-25 14:17:07 +0300
commit166877cf15f6afa89c9f8a61e267d485868d0ee1 (patch)
tree9f080314edc4fb293f91227cdc1c01cfec8d7bae /src/un_memory.c
parent8ebdc95621bc61fdf3c98cd7ae4ddca67398df23 (diff)
downloadungrateful-166877cf15f6afa89c9f8a61e267d485868d0ee1.tar.gz
ungrateful-166877cf15f6afa89c9f8a61e267d485868d0ee1.zip
+disgrace and rework of ungrateful.h
Diffstat (limited to 'src/un_memory.c')
-rw-r--r--src/un_memory.c282
1 files changed, 94 insertions, 188 deletions
diff --git a/src/un_memory.c b/src/un_memory.c
index 178fcbc..dd1bc87 100644
--- a/src/un_memory.c
+++ b/src/un_memory.c
@@ -2,267 +2,173 @@
/// -------- Basic functions
-void un_memory_set(u8 *buffer, u8 value, u64 size) {
- if (size == 0) return;
- assert(buffer != NULL);
-
- while (size-- > 0) {
- *buffer++ = value;
- }
-}
-
-void un_memory_copy(u8 *dest, u8 *source, u64 size) {
- if (size == 0) return;
-
- assert(dest != NULL);
- assert(source != NULL);
-
-#ifdef DEBUG
-
- if (dest < source) {
- assert(((ptrdiff_t)source - (ptrdiff_t)dest) >= (ptrdiff_t)size);
- } else {
- assert(((ptrdiff_t)dest - (ptrdiff_t)source) >= (ptrdiff_t)size);
- }
-#endif // DEBUG
-
- while (size-- > 0) {
- *dest++ = *source++;
- }
-}
-
-s32 un_memory_compare(u8 *left, u8 *right, u64 size) {
- while (size-- > 0) {
- if (*left++ == *right++)
- continue;
-
- return left[-1] > right[-1] ? 1 : -1;
- }
-
- return 0;
-}
-
-void un_memory_move(u8 *dest, u8 *src, u64 size) {
- Allocator talloc = un_allocator_get_temporary();
-
- void *temp = un_memory_alloc(size, talloc);
-
- un_memory_copy(temp, src, size);
- un_memory_copy(dest, temp, size);
-}
-
void *un_memory_alloc(u64 size, Allocator alloc) {
assert(alloc.proc != NULL);
- return alloc.proc(NULL, size, UN_ALLOC_MSG_ALLOCATE, alloc.data);
+ return alloc.proc(NULL, size, UN_DEFAULT_ALIGN, UN_ALLOC_MSG_ALLOCATE, alloc.data);
}
-void un_memory_free(void *ptr, Allocator alloc) {
+void *un_memory_alloc_align(u64 size, u32 align, Allocator alloc) {
assert(alloc.proc != NULL);
- alloc.proc(ptr, 0, UN_ALLOC_MSG_FREE, alloc.data);
+ return alloc.proc(NULL, size, align, UN_ALLOC_MSG_ALLOCATE, alloc.data);
}
-void un_memory_destroy(Allocator *alloc) {
- assert(alloc != NULL);
- assert(alloc->proc != NULL);
-
- alloc->proc(NULL, 0, UN_ALLOC_MSG_SELF_DELETE, alloc->data);
-
- UN_CLEAR(*alloc);
+void un_memory_free(void *ptr, Allocator alloc) {
+ assert(alloc.proc != NULL);
+ alloc.proc(ptr, 0, 0, UN_ALLOC_MSG_FREE, alloc.data);
}
-/// -------- Stdlib allocator
+/// -------- Std allocator
#if defined(OS_WINDOWS)
-#include "un_mem_win_x64.c"
-
+# include "un_mem_win_x64.c"
#elif defined(OS_LINUX)
-#include "un_mem_linux_x64.c"
-
+# include "un_mem_linux_x64.c"
#else
-#include "un_mem_std.c"
-
+# include "un_mem_std.c"
#endif
-Allocator un_allocator_get_standard(void) {
+Allocator un_alloc_std_get(void) {
return CLITERAL(Allocator) { .proc = un_std_alloc_proc };
}
-/// -------- Temp allocator
-
-static struct {
- u64 index;
- u8 data[UN_TEMP_SIZE];
-} _temp;
-
-static void temp_reset(void) {
- _temp.index = 0;
-}
+/// Arena allocator
-static void *temp_alloc(u64 size) {
- if ((_temp.index + size) > UN_TEMP_SIZE) {
- // @todo: Decice what is the best behaviour for wrapping
- assert(false);
- temp_reset();
- }
+typedef struct Arena {
+ u8 *buffer;
+ u64 size, curr_offset, prev_offset;
+} Arena;
- if ((_temp.index + size) > UN_TEMP_SIZE) {
- return NULL;
- }
+static Arena __temp_arena;
- void *ptr = (u8*)_temp.data + _temp.index;
- _temp.index += size;
- un_memory_set(ptr, 0x00, size);
+static Arena arena_create(u64 size) {
+ Allocator alloc;
+ Arena arena;
- return ptr;
-}
+ UN_CLEAR(arena);
-static ALLOCATOR_PROC_SIGNATURE(un_temp_alloc_proc) {
- UNUSED(data);
- UNUSED(p);
+ alloc = un_alloc_std_get();
+ arena.buffer = un_memory_alloc(size, alloc);
- switch (message) {
- case UN_ALLOC_MSG_ALLOCATE:
- return temp_alloc(size);
- case UN_ALLOC_MSG_FREE:
- break;
- case UN_ALLOC_MSG_SELF_DELETE: break;
+ if (arena.buffer == NULL) {
+ return arena;
}
- return NULL;
+ arena.size = size;
+ return arena;
}
-Allocator un_allocator_get_temporary(void) {
- return CLITERAL(Allocator) { .proc = un_temp_alloc_proc };
-}
+// special thanks to ginger bill: https://www.gingerbill.org/article/2019/02/08/memory-allocation-strategies-002/
+static uintptr_t align_forward(uintptr_t ptr, u32 align) {
+ uintptr_t p, a, modulo;
-/// Arena allocator
+ assert(UN_POW_OF2(align));
-typedef struct Arena {
- u64 size;
- u64 occupied;
- struct Arena *next;
- u8 data[1];
-} Arena;
+ p = ptr;
+ a = (uintptr_t)align;
+ modulo = p & (a-1);
-static Arena *arena_create(u64 size) {
- Allocator alloc;
- Arena *arena;
+ if (modulo != 0) {
+ p += a - modulo;
+ }
- alloc = un_allocator_get_standard();
- arena = CLITERAL(Arena*)un_memory_alloc(size, alloc);
+ return p;
+}
- if (!arena) {
- return NULL;
- }
+static void* arena_allocate_align(Arena *arena, u32 align, u64 size) {
+ uintptr_t curr_ptr, offset;
+ u8 *ptr;
- UN_CLEAR(*arena);
- arena->size = size - sizeof(Arena);
- return arena;
-}
+ assert(arena != NULL);
-static void arena_delete(Arena *arena) {
- if (arena->next != NULL) {
- arena_delete(arena->next);
+ curr_ptr = (uintptr_t)arena->buffer + arena->curr_offset;
+ offset = align_forward(curr_ptr, align);
+ offset -= (uintptr_t)arena->buffer;
+
+ if ((offset + size) <= arena->size) {
+ ptr = (u8*)(arena->buffer + offset);
+ arena->prev_offset = offset;
+ arena->curr_offset = offset + size;
+ memset(ptr, 0, size);
+ } else {
+ ptr = NULL;
}
- Allocator alloc = un_allocator_get_standard();
- un_memory_free(arena, alloc);
+ return ptr;
}
-static void *arena_allocate(u64 size, Arena *arena) {
- u8* pos;
-
- if (size <= (arena->size - arena->occupied)) {
- pos = arena->data + arena->occupied;
- arena->occupied += size;
- return (void*)pos;
- }
+static void arena_free_memory(Arena *arena) {
+ if (arena == &__temp_arena) return;
- if (!arena->next) {
- arena->next = arena_create((arena->size + sizeof(Arena)) * 2LL);
- }
+ assert(arena != NULL);
- return arena_allocate(size, arena->next);
+ if (arena->buffer != NULL) {
+ un_memory_free(arena->buffer, un_alloc_std_get());
+ }
}
static ALLOCATOR_PROC_SIGNATURE(un_arena_alloc_proc) {
- assert(data != NULL);
UNUSED(p);
switch (message) {
case UN_ALLOC_MSG_ALLOCATE:
- return arena_allocate(size, (Arena*)data);
+ return arena_allocate_align((Arena*)data, align, size);
case UN_ALLOC_MSG_FREE:
break;
case UN_ALLOC_MSG_SELF_DELETE:
- arena_delete((Arena*)data);
+ arena_free_memory((Arena*)data);
break;
}
return NULL;
}
-Allocator un_allocator_create_arena(u64 size) {
- Allocator alloc = { 0 };
+Allocator un_alloc_arena_create(u64 byte_size) {
+ Allocator alloc, std;
+ Arena arena;
+ UN_CLEAR(alloc);
+ std = un_alloc_std_get();
alloc.proc = un_arena_alloc_proc;
- alloc.data = arena_create(size);
-
- return alloc;
-}
+ arena = arena_create(byte_size);
-/// Wrapping allocator
+ if(arena.buffer == NULL) {
+ UN_CLEAR(alloc);
+ }
+ alloc.data = un_memory_alloc(sizeof(arena), std); // yeah, it allocs 4kb for 32 bytes...
-typedef struct Allocation_Info {
- void *p;
- u64 size;
-} Allocation_Info;
+ if(alloc.data == NULL) {
+ arena_free_memory(&arena);
+ UN_CLEAR(alloc);
+ return alloc;
+ }
-typedef struct Wrapper {
- // we need to create hashmap and add all allocations in here
- // List allocations;
- Allocator target;
-} Wrapper;
+ *((Arena *)alloc.data) = arena;
+ return alloc;
+}
-static Wrapper *wrapper_create(Allocator target) {
- Wrapper *wrapper = (Wrapper *)un_memory_alloc(sizeof(Wrapper), un_allocator_get_standard());
+void un_alloc_arena_destroy(Allocator *alloc) {
+ arena_free_memory((Arena*)alloc->data);
- un_memory_set((void*)wrapper, 0, sizeof(Wrapper));
- wrapper->target = target;
+ un_memory_free(alloc->data, un_alloc_std_get());
- return wrapper;
+ UN_CLEAR(*alloc);
}
-static void wrapper_destroy(Wrapper *wrapper) {
- assert(wrapper != NULL);
- un_memory_free(wrapper, un_allocator_get_standard());
+void un_alloc_temp_init(u64 byte_size) {
+ __temp_arena = arena_create(byte_size);
}
-static ALLOCATOR_PROC_SIGNATURE(un_wrapper_alloc_proc) {
- assert(data != NULL);
+void un_alloc_temp_reset(void) {
+ __temp_arena.curr_offset = 0;
+ __temp_arena.prev_offset = 0;
+}
- switch (message) {
- case UN_ALLOC_MSG_ALLOCATE:
- return un_memory_alloc(size, ((Wrapper*)data)->target);
- case UN_ALLOC_MSG_FREE:
- un_memory_free(p, ((Wrapper*)data)->target);
- break;
- case UN_ALLOC_MSG_SELF_DELETE:
- un_memory_destroy(&((Wrapper*)data)->target);
- wrapper_destroy((Wrapper*)data);
- break;
- }
+Allocator un_alloc_temp_get(void) {
+ assert(__temp_arena.buffer != NULL);
- return NULL;
+ return CLITERAL(Allocator) { un_arena_alloc_proc, &__temp_arena };
}
-Allocator un_allocator_create_wrapper(Allocator target) {
- Allocator alloc = { 0 };
-
- alloc.proc = un_wrapper_alloc_proc;
- alloc.data = wrapper_create(target);
- return alloc;
-}