diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-10 23:50:41 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-10 23:50:41 +0100 |
| commit | fd8128d9b84e362abdbd05fafe252421edee8ab2 (patch) | |
| tree | 4350d5b79a2e0e225dd4bb32511d4b8bd85a1338 | |
| parent | 96d060679a4c34c30a346f1945f88cb8ef45f657 (diff) | |
Redesign with sbrk(2)
So far, tinyalloc was designed for a static heap area, failing to
allocate whenever the end boundary was reached.
Unfortunately, this design was too limiting if the same library were to
be used for WebAssembly applications, where interpreters are required to
implement the current_memory and grow_memory operators. [1]
Whereas the former returns the number of currently allocated pages by
the interpreter (64 KiB being the standard page size), the latter must
increase that number by the number of pages required by the caller, but
without exceeding the maximum limit imposed by the application
developer.
Since WebAssembly's grow_memory is usually converted to sbrk(2) by
implementations, tinyalloc now makes use of this traditional syscall to
achieve the desired effect.
[1]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefsyntax-instr-memorymathsfmemorygrow
| -rw-r--r-- | tinyalloc.c | 23 | ||||
| -rw-r--r-- | tinyalloc.h | 3 |
2 files changed, 14 insertions, 12 deletions
diff --git a/tinyalloc.c b/tinyalloc.c index 36e9093..69eaeb5 100644 --- a/tinyalloc.c +++ b/tinyalloc.c @@ -1,5 +1,6 @@ #include "tinyalloc.h" #include <stddef.h> +#include <unistd.h> #ifdef TA_DEBUG extern void print_s(char *); @@ -111,9 +112,11 @@ static void compact() { } #endif -bool ta_init(void *base, const void *limit, const size_t heap_blocks, const size_t split_thresh, const size_t alignment) { +bool ta_init(const size_t heap_blocks, const size_t split_thresh, const size_t alignment) { + void *base = sbrk(sizeof *heap + sizeof (Block) * heap_blocks); + if (!base) + return false; heap = (Heap *)base; - heap_limit = limit; heap_split_thresh = split_thresh; heap_alignment = alignment; heap_max_blocks = heap_blocks; @@ -121,7 +124,8 @@ bool ta_init(void *base, const void *limit, const size_t heap_blocks, const size heap->free = NULL; heap->used = NULL; heap->fresh = (Block *)(heap + 1); - heap->top = (size_t)(heap->fresh + heap_blocks); + heap_limit = heap->fresh + heap_blocks; + heap->top = (size_t)heap_limit; Block *block = heap->fresh; size_t i = heap_max_blocks - 1; @@ -199,15 +203,18 @@ static Block *alloc_block(size_t num) { } // no matching free blocks // see if any other blocks available - size_t new_top = top + num; - if (heap->fresh != NULL && new_top <= (size_t)heap_limit) { + if (heap->fresh != NULL) { + void *new_top = sbrk(num); + if(new_top == NULL) + return NULL; ptr = heap->fresh; heap->fresh = ptr->next; ptr->addr = (void *)top; ptr->next = heap->used; ptr->size = num; heap->used = ptr; - heap->top = new_top; + heap->top = (size_t)new_top + num; + heap_limit = (char *)heap->top; return ptr; } return NULL; @@ -303,7 +310,3 @@ size_t ta_num_used() { size_t ta_num_fresh() { return count_blocks(heap->fresh); } - -bool ta_check() { - return heap_max_blocks == ta_num_free() + ta_num_used() + ta_num_fresh(); -} diff --git a/tinyalloc.h b/tinyalloc.h index c845eea..329ff89 100644 --- a/tinyalloc.h +++ b/tinyalloc.h @@ -5,7 +5,7 @@ extern "C" { #include <stdbool.h> #include <stddef.h> -bool ta_init(void *base, const void *limit, const size_t heap_blocks, const size_t split_thresh, const size_t alignment); +bool ta_init(const size_t heap_blocks, const size_t split_thresh, const size_t alignment); void *ta_alloc(size_t num); void *ta_realloc(void *ptr, size_t n); void *ta_calloc(size_t num, size_t size); @@ -14,7 +14,6 @@ bool ta_free(void *ptr); size_t ta_num_free(); size_t ta_num_used(); size_t ta_num_fresh(); -bool ta_check(); #ifdef __cplusplus } |
