aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-11-10 23:50:41 +0100
committerXavier Del Campo Romero <xavi92@disroot.org>2025-11-10 23:50:41 +0100
commitfd8128d9b84e362abdbd05fafe252421edee8ab2 (patch)
tree4350d5b79a2e0e225dd4bb32511d4b8bd85a1338
parent96d060679a4c34c30a346f1945f88cb8ef45f657 (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.c23
-rw-r--r--tinyalloc.h3
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
}