diff options
| author | Matt Reyer <270504+winduptoy@users.noreply.github.com> | 2019-07-01 19:54:58 -0400 |
|---|---|---|
| committer | Matt Reyer <270504+winduptoy@users.noreply.github.com> | 2019-07-01 20:07:36 -0400 |
| commit | 824a6403417482a3349616514ebdea3f790c271e (patch) | |
| tree | 061ac06af22117b10d5eb26be2acc17e7f109ea7 | |
| parent | 9ebd4a406bf783a68b0e0ba57545f11f12bf5827 (diff) | |
Move compile-time configuration into a runtime configuration.
- Updated README
| -rw-r--r-- | README.md | 25 | ||||
| -rw-r--r-- | tinyalloc.c | 56 | ||||
| -rw-r--r-- | tinyalloc.h | 2 |
3 files changed, 36 insertions, 47 deletions
@@ -33,10 +33,21 @@ The list of freed blocks is sorted by block start address. When a block is being ## API -### ta\_init() +### ta\_init(void \*base, void \*limit, size_t heap_blocks, size_t split_thresh, size_t alignment) Initializes the control datastructure. MUST be called prior to any other **tinyalloc** function. +| Argument | Description | +|----------|-------------| +| `base` | Address of **tinyalloc** control structure, typically at the beginning of your heap | +| `limit` | Heap space end address | +| `heap_blocks` | Max. number of memory chunks (e.g. 256) | +| `split_thresh` | Size threshold for splitting chunks (a good default is 16) | +| `alignment` | Word size for pointer alignment (e.g. 8) | + +- `alignment` is assumed to be >= native word size +- `base` must be an address in RAM (on embedded devices) + ### void* ta\_alloc(size\_t num) Like standard `malloc`, returns aligned pointer to address in heap space, or `NULL` if allocation failed. @@ -45,7 +56,7 @@ Like standard `malloc`, returns aligned pointer to address in heap space, or `NU Like standard `calloc`, returns aligned pointer to zeroed memory in heap space, or `NULL` if allocation failed. -### bool ta\_free(void *ptr) +### bool ta\_free(void \*ptr) Like `free`, but returns boolean result (true, if freeing succeeded). By default, any consecutive memory blocks are being merged during the freeing operation. @@ -59,24 +70,14 @@ Structural validation. Returns `true` if internal heap structure is ok. | Define | Default | Comment | |--------|---------|---------| -| `TA_ALIGN` | 8 | Word size for pointer alignment | -| `TA_BASE` | 0x400 | Address of **tinyalloc** control data structure | | `TA_DEBUG` | undefined | Trace debug information | | `TA_DISABLE_COMPACT` | undefined | Disable free block compaction | | `TA_DISABLE_SPLIT` | undefined | Disable free block splitting during re-alloc | -| `TA_HEAP_START` | 0x1010 | Heap space start address | -| `TA_HEAP_LIMIT` | 0xffffff | Heap space end address | -| `TA_HEAP_BLOCKS` | 256 | Max. number of memory chunks | -| `TA_SPLIT_THRESH` | 16 | Size threshold for splitting chunks | On a 32bit system, the default configuration causes an overhead of 3088 bytes in RAM, but can be reduced if fewer memory blocks are needed. **Notes:** -- `TA_ALIGN` is assumed to be >= native word size -- `TA_BASE` must be an address in RAM (on embedded devices) -- `TA_HEAP_START` is assumed to be properly aligned - If building in debug mode (if `TA_DEBUG` symbol is defined), two externally defined functions are required: - `print_s(char *)` - to print a single string diff --git a/tinyalloc.c b/tinyalloc.c index 066fecc..a12409e 100644 --- a/tinyalloc.c +++ b/tinyalloc.c @@ -1,30 +1,6 @@ #include "tinyalloc.h" #include <stdint.h> -#ifndef TA_ALIGN -#define TA_ALIGN 8 -#endif - -#ifndef TA_BASE -#define TA_BASE 0x400 -#endif - -#ifndef TA_HEAP_START -#define TA_HEAP_START (TA_BASE + sizeof(Heap)) -#endif - -#ifndef TA_HEAP_LIMIT -#define TA_HEAP_LIMIT (1 << 24) -#endif - -#ifndef TA_HEAP_BLOCKS -#define TA_HEAP_BLOCKS 256 -#endif - -#ifndef TA_SPLIT_THRESH -#define TA_SPLIT_THRESH 16 -#endif - #ifdef TA_DEBUG extern void print_s(char *); extern void print_i(size_t); @@ -46,10 +22,14 @@ typedef struct { Block *used; // first used block Block *fresh; // first available blank block size_t top; // top free addr - Block blocks[TA_HEAP_BLOCKS]; + Block *blocks; } Heap; -static Heap *heap = (Heap *)TA_BASE; +static Heap *heap = NULL; +static void *heap_limit = NULL; +static size_t heap_split_thresh; +static size_t heap_alignment; +static size_t heap_max_blocks; /** * If compaction is enabled, inserts block @@ -132,13 +112,21 @@ static void compact() { } #endif -bool ta_init() { +bool ta_init(const void *base, const void *limit, const size_t heap_blocks, const size_t split_thresh, const size_t alignment) { + heap = (Heap *)base; + heap_limit = limit; + heap_split_thresh = split_thresh; + heap_alignment = alignment; + heap_max_blocks = heap_blocks; + heap->free = NULL; heap->used = NULL; heap->fresh = heap->blocks; - heap->top = TA_HEAP_START; + heap->top = (size_t)base + sizeof(Heap) + heap_blocks * sizeof(Block); + heap->blocks = base + sizeof(Heap); + Block *block = heap->blocks; - size_t i = TA_HEAP_BLOCKS - 1; + size_t i = heap_max_blocks - 1; while (i--) { block->next = block + 1; block++; @@ -173,9 +161,9 @@ static Block *alloc_block(size_t num) { Block *ptr = heap->free; Block *prev = NULL; size_t top = heap->top; - num = (num + TA_ALIGN - 1) & -TA_ALIGN; + num = (num + heap_alignment - 1) & -heap_alignment; while (ptr != NULL) { - const int is_top = ((size_t)ptr->addr + ptr->size >= top) && ((size_t)ptr->addr + num <= TA_HEAP_LIMIT); + const int is_top = ((size_t)ptr->addr + ptr->size >= top) && ((size_t)ptr->addr + num <= heap_limit); if (is_top || ptr->size >= num) { if (prev != NULL) { prev->next = ptr->next; @@ -191,7 +179,7 @@ static Block *alloc_block(size_t num) { #ifndef TA_DISABLE_SPLIT } else if (heap->fresh != NULL) { size_t excess = ptr->size - num; - if (excess >= TA_SPLIT_THRESH) { + if (excess >= heap_split_thresh) { ptr->size = num; Block *split = heap->fresh; heap->fresh = split->next; @@ -214,7 +202,7 @@ 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 <= TA_HEAP_LIMIT) { + if (heap->fresh != NULL && new_top <= heap_limit) { ptr = heap->fresh; heap->fresh = ptr->next; ptr->addr = (void *)top; @@ -280,5 +268,5 @@ size_t ta_num_fresh() { } bool ta_check() { - return TA_HEAP_BLOCKS == ta_num_free() + ta_num_used() + ta_num_fresh(); + return heap_max_blocks == ta_num_free() + ta_num_used() + ta_num_fresh(); } diff --git a/tinyalloc.h b/tinyalloc.h index 6a76d2a..947af94 100644 --- a/tinyalloc.h +++ b/tinyalloc.h @@ -1,7 +1,7 @@ #include <stdbool.h> #include <stddef.h> -bool ta_init(); +bool ta_init(const void *base, const void *limit, const size_t heap_blocks, const size_t split_thresh, const size_t alignment); void *ta_alloc(size_t num); void *ta_calloc(size_t num, size_t size); bool ta_free(void *ptr); |
