From 3abf5e3f7f8263ccbc096a65cc148f81bbeb63aa Mon Sep 17 00:00:00 2001 From: flysand7 Date: Fri, 28 Jul 2023 21:49:56 +1100 Subject: [PATCH] Memory API --- include/cia-mem.h | 32 +++++++++++++++++++++++++++++++ include/tinyrt.h | 7 +++++++ src/impl/cia-mem/allocator.c | 37 ++++++++++++++++++++++++++++++++++++ src/impl/cia-mem/arena.c | 35 ++++++++++++++++++++++++++++++++++ src/impl/cia-mem/util.c | 12 ++++++++++++ src/library.json | 13 +++++++++++++ src/linux/tinyrt.json | 1 + src/windows/tinyrt.c | 17 +++++++++++++++++ src/windows/tinyrt.json | 1 + 9 files changed, 155 insertions(+) create mode 100644 include/cia-mem.h create mode 100644 src/impl/cia-mem/allocator.c create mode 100644 src/impl/cia-mem/arena.c create mode 100644 src/impl/cia-mem/util.c diff --git a/include/cia-mem.h b/include/cia-mem.h new file mode 100644 index 0000000..9700267 --- /dev/null +++ b/include/cia-mem.h @@ -0,0 +1,32 @@ + +#pragma once + +void *cia_ptr_alignf(void *ptr, u64 alignment); +void *cia_ptr_alignb(void *ptr, u64 alignment); + +struct Cia_Allocator typedef Cia_Allocator; +struct Cia_Allocator { + void *ctx; + void *(*alloc)(void *ctx, u64 size); + void *(*alloc_a)(void *ctx, u64 size, u64 alignment); + void (*free)(void *ctx, void *ptr); + void (*free_all)(void *ctx, void *ptr); + void *(*realloc)(void *ctx, void *ptr, u64 new_size); +}; + +Cia_Allocator cia_allocator_null(); +Cia_Allocator cia_allocator_pages(); + +struct Cia_Arena typedef Cia_Arena; +struct Cia_Arena { + Cia_Allocator allocator; + u64 buffer_size; + u64 used; + u8* buffer; +}; + +void cia_arena_create(Cia_Arena *arena, Cia_Allocator backing_allocator, u64 max_size); +void *cia_arena_alloc(Cia_Arena *arena, u64 size); +void *cia_arena_alloc_aligned(Cia_Arena *arena, u64 size, u64 align); +void cia_arena_free_all(Cia_Arena *arena); +void cia_arena_destroy(Cia_Arena *arena); diff --git a/include/tinyrt.h b/include/tinyrt.h index a8fa692..2da36d6 100644 --- a/include/tinyrt.h +++ b/include/tinyrt.h @@ -5,6 +5,7 @@ #define _RT_STATUS_OK 0 // No errors #define _RT_ERROR_NOT_IMPLEMENTED -1 // Function not implemented #define _RT_ERROR_BAD_PARAM -2 // One of the function parameters was wrong +#define _RT_ERROR_GENERIC -3 // Just any random error // File API errors #define _RT_STATUS_FILE_ACCESS 1 // No access to the file @@ -69,3 +70,9 @@ struct _RT_File { static _RT_Status _rt_file_write(_RT_File *to, u64 size, void *buffer, u64 *out_bytes_written); static _RT_Status _rt_file_close(_RT_File *file); #endif + +// Memory API +#if _RT_API_MEMORY == 1 + static _RT_Status _rt_mem_alloc(void *optional_desired_addr, u64 min_size, void **out_addr); + static _RT_Status _rt_mem_free(void *ptr); +#endif diff --git a/src/impl/cia-mem/allocator.c b/src/impl/cia-mem/allocator.c new file mode 100644 index 0000000..12ad51e --- /dev/null +++ b/src/impl/cia-mem/allocator.c @@ -0,0 +1,37 @@ + +Cia_Allocator cia_allocator_null() { + Cia_Allocator allocator = { + .ctx = NULL, + .alloc = NULL, + .alloc_a = NULL, + .free = NULL, + .free_all = NULL, + .realloc = NULL + }; + return allocator; +} + +static void *page_alloc(void *ctx, u64 size) { + void *addr; + _RT_Status status = _rt_mem_alloc(NULL, size, &addr); + if(status != _RT_STATUS_OK) { + return NULL; + } + return addr; +} + +static void page_free(void *ptr) { + _rt_mem_free(ptr); +} + +Cia_Allocator cia_allocator_pages() { + Cia_Allocator allocator = { + .ctx = NULL, + .alloc = page_alloc, + .alloc_a = NULL, + .free = page_free, + .free_all = NULL, + .realloc = NULL, + }; + return allocator; +} diff --git a/src/impl/cia-mem/arena.c b/src/impl/cia-mem/arena.c new file mode 100644 index 0000000..45d2e24 --- /dev/null +++ b/src/impl/cia-mem/arena.c @@ -0,0 +1,35 @@ + +void cia_arena_create(Cia_Arena *arena, Cia_Allocator backing_allocator, u64 buffer_size) { + arena->allocator = backing_allocator; + arena->buffer_size = buffer_size; + arena->used = 0; + arena->buffer = arena->allocator.alloc(arena->allocator.ctx, buffer_size); +} + +void *cia_arena_alloc(Cia_Arena *arena, u64 size) { + if(arena->used + size > arena->buffer_size) { + return NULL; + } + void *ptr = &arena->buffer[arena->used]; + arena->used += arena->buffer_size; + return ptr; +} + +void *cia_arena_alloc_aligned(Cia_Arena *arena, u64 size, u64 align) { + void *buffer_end = &arena->buffer[arena->buffer_size]; + void *region_ptr = cia_ptr_alignf(&arena->buffer[arena->used], align); + void *region_end = (void *)((u64)region_ptr + size); + if(region_end > buffer_end) { + return NULL; + } + arena->used = (u64)region_ptr - (u64)arena->buffer; + return region_ptr; +} + +void cia_arena_free_all(Cia_Arena *arena) { + arena->used = 0; +} + +void cia_arena_destroy(Cia_Arena *arena) { + arena->allocator.free(arena->allocator.ctx, arena->buffer); +} diff --git a/src/impl/cia-mem/util.c b/src/impl/cia-mem/util.c new file mode 100644 index 0000000..d33ed99 --- /dev/null +++ b/src/impl/cia-mem/util.c @@ -0,0 +1,12 @@ + +void *cia_ptr_alignf(void *ptr, u64 alignment) { + u64 addr = (u64)ptr; + u64 aligned = (addr + alignment - 1) & ~(alignment - 1); + return (void *)aligned; +} + +void *cia_ptr_alignb(void *ptr, u64 alignment) { + u64 addr = (u64)ptr; + u64 aligned = addr & ~(alignment - 1); + return (void *)aligned; +} \ No newline at end of file diff --git a/src/library.json b/src/library.json index 616554a..df0b7fc 100644 --- a/src/library.json +++ b/src/library.json @@ -24,6 +24,7 @@ includes: [ "stdlib.h", "stdio.h", + "cia-mem.h", ], platforms: [ @@ -53,6 +54,18 @@ platforms: [ ], apis: [ + { + name: "cia_memory", + path: "impl/cia-mem", + includes: [ + "util.c", + "allocator.c", + "arena.c", + ], + reqs: [ + "rt_api_memory" + ] + }, { name: "stdlib_program", path: "impl/stdlib-program", diff --git a/src/linux/tinyrt.json b/src/linux/tinyrt.json index 85639ae..32d09dd 100644 --- a/src/linux/tinyrt.json +++ b/src/linux/tinyrt.json @@ -7,3 +7,4 @@ rt_api_file: true, rt_api_program: true, rt_api_shell: false, +rt_api_memory: false, diff --git a/src/windows/tinyrt.c b/src/windows/tinyrt.c index adc7680..af72ab2 100644 --- a/src/windows/tinyrt.c +++ b/src/windows/tinyrt.c @@ -74,3 +74,20 @@ static _RT_Status _rt_file_close(_RT_File *file) { __builtin_unreachable(); } +static _RT_Status _rt_mem_alloc(void *optional_desired_addr, u64 min_size, void **out_addr) { + void *addr = VirtualAlloc(optional_desired_addr, min_size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + *out_addr = addr; + if(addr == NULL) { + return _RT_ERROR_GENERIC; + } + return _RT_STATUS_OK; +} + +static _RT_Status _rt_mem_free(void *addr) { + BOOL ok = VirtualFree(addr, 0, MEM_RELEASE); + if(!ok) { + return _RT_ERROR_GENERIC; + } + return _RT_STATUS_OK; +} + diff --git a/src/windows/tinyrt.json b/src/windows/tinyrt.json index acea106..7278cd6 100644 --- a/src/windows/tinyrt.json +++ b/src/windows/tinyrt.json @@ -6,3 +6,4 @@ rt_api_file: true, rt_api_program: true, rt_api_shell: false, +rt_api_memory: true, \ No newline at end of file