Skip to content

Commit 40e2666

Browse files
committed
Allow multiple tinyalloc heaps (eliminate static variables)
Multiple heaps can be useful for dividing memory into multiple areas that can be used for different purposes, with individual limits. - Add a config struct (ta_cfg_t, can be declared const) - Pass config pointer to all tinyalloc functions
1 parent fce0c31 commit 40e2666

File tree

2 files changed

+66
-62
lines changed

2 files changed

+66
-62
lines changed

tinyalloc.c

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "tinyalloc.h"
2+
23
#include <stdint.h>
34

45
#ifdef TA_DEBUG
@@ -30,19 +31,13 @@ typedef struct {
3031
size_t top; // top free addr
3132
} Heap;
3233

33-
static Heap *heap = NULL;
34-
static const void *heap_limit = NULL;
35-
static size_t heap_split_thresh;
36-
static size_t heap_alignment;
37-
static size_t heap_max_blocks;
38-
3934
/**
4035
* If compaction is enabled, inserts block
4136
* into free list, sorted by addr.
4237
* If disabled, add block has new head of
4338
* the free list.
4439
*/
45-
static void insert_block(Block *block) {
40+
static void insert_block(Heap *heap, Block *block) {
4641
#ifndef TA_DISABLE_COMPACT
4742
Block *ptr = heap->free;
4843
Block *prev = NULL;
@@ -72,7 +67,7 @@ static void insert_block(Block *block) {
7267
}
7368

7469
#ifndef TA_DISABLE_COMPACT
75-
static void release_blocks(Block *scan, Block *to) {
70+
static void release_blocks(Heap *heap, Block *scan, Block *to) {
7671
Block *scan_next;
7772
while (scan != to) {
7873
print_s("release");
@@ -86,7 +81,7 @@ static void release_blocks(Block *scan, Block *to) {
8681
}
8782
}
8883

89-
static void compact() {
84+
static void compact(Heap *heap) {
9085
Block *ptr = heap->free;
9186
Block *prev;
9287
Block *scan;
@@ -108,7 +103,7 @@ static void compact() {
108103
ptr->size = new_size;
109104
Block *next = prev->next;
110105
// make merged blocks available
111-
release_blocks(ptr->next, prev->next);
106+
release_blocks(heap, ptr->next, prev->next);
112107
// relink
113108
ptr->next = next;
114109
}
@@ -117,32 +112,27 @@ static void compact() {
117112
}
118113
#endif
119114

120-
bool ta_init(const void *base, const void *limit, const size_t heap_blocks, const size_t split_thresh, const size_t alignment) {
121-
heap = (Heap *)base;
122-
heap_limit = limit;
123-
heap_split_thresh = split_thresh;
124-
heap_alignment = alignment;
125-
heap_max_blocks = heap_blocks;
126-
127-
heap->free = NULL;
128-
heap->used = NULL;
129-
heap->fresh = (Block *)(heap + 1);
130-
heap->top = (size_t)(heap->fresh + heap_blocks);
115+
void ta_init(const ta_cfg_t *cfg) {
116+
Heap *heap = (Heap *)cfg->base;
117+
heap->free = NULL;
118+
heap->used = NULL;
119+
heap->fresh = (Block *)(heap + 1);
120+
heap->top = (size_t)(heap->fresh + cfg->max_blocks);
131121

132122
Block *block = heap->fresh;
133-
size_t i = heap_max_blocks - 1;
123+
size_t i = cfg->max_blocks - 1;
134124
while (i--) {
135125
block->next = block + 1;
136126
block++;
137127
}
138128
block->next = NULL;
139-
return true;
140129
}
141130

142-
bool ta_free(void *free) {
131+
bool ta_free(const ta_cfg_t *cfg, void *free) {
143132
if (free == NULL) {
144133
return false;
145134
}
135+
Heap *heap = (Heap *)cfg->base;
146136
Block *block = heap->used;
147137
Block *prev = NULL;
148138
while (block != NULL) {
@@ -152,9 +142,9 @@ bool ta_free(void *free) {
152142
} else {
153143
heap->used = block->next;
154144
}
155-
insert_block(block);
145+
insert_block(heap, block);
156146
#ifndef TA_DISABLE_COMPACT
157-
compact();
147+
compact(heap);
158148
#endif
159149
return true;
160150
}
@@ -164,20 +154,21 @@ bool ta_free(void *free) {
164154
return false;
165155
}
166156

167-
static Block *alloc_block(size_t num) {
157+
static Block *alloc_block(const ta_cfg_t *cfg, size_t num) {
158+
Heap *heap = (Heap *)cfg->base;
168159
Block *ptr = heap->free;
169160
Block *prev = NULL;
170161
size_t top = heap->top;
171-
if (num > -heap_alignment) {
162+
if (num > -cfg->alignment) {
172163
return NULL; // prevent overflow
173164
}
174-
num = (num + heap_alignment - 1) & -heap_alignment;
165+
num = (num + cfg->alignment - 1) & -cfg->alignment;
175166
if (num == 0) {
176-
num = heap_alignment; // prevent zero-size block
167+
num = cfg->alignment; // prevent zero-size block
177168
}
178169
while (ptr != NULL) {
179170
const int is_top = ((size_t)ptr->addr + ptr->size >= top) &&
180-
(num <= (size_t)heap_limit - (size_t)ptr->addr);
171+
(num <= (size_t)cfg->limit - (size_t)ptr->addr);
181172
if (is_top || ptr->size >= num) {
182173
if (prev != NULL) {
183174
prev->next = ptr->next;
@@ -193,17 +184,17 @@ static Block *alloc_block(size_t num) {
193184
#ifndef TA_DISABLE_SPLIT
194185
} else if (heap->fresh != NULL) {
195186
size_t excess = ptr->size - num;
196-
if (excess >= heap_split_thresh) {
187+
if (excess >= cfg->split_thresh) {
197188
ptr->size = num;
198189
Block *split = heap->fresh;
199190
heap->fresh = split->next;
200191
split->addr = (void *)((size_t)ptr->addr + num);
201192
print_s("split");
202193
print_i((size_t)split->addr);
203194
split->size = excess;
204-
insert_block(split);
195+
insert_block(heap, split);
205196
#ifndef TA_DISABLE_COMPACT
206-
compact();
197+
compact(heap);
207198
#endif
208199
}
209200
#endif
@@ -215,7 +206,7 @@ static Block *alloc_block(size_t num) {
215206
}
216207
// no matching free blocks
217208
// see if any other blocks available
218-
if (heap->fresh != NULL && (num <= (size_t)heap_limit - top)) {
209+
if (heap->fresh != NULL && (num <= (size_t)cfg->limit - top)) {
219210
ptr = heap->fresh;
220211
heap->fresh = ptr->next;
221212
ptr->addr = (void *)top;
@@ -228,8 +219,8 @@ static Block *alloc_block(size_t num) {
228219
return NULL;
229220
}
230221

231-
void *ta_alloc(size_t num) {
232-
Block *block = alloc_block(num);
222+
void *ta_alloc(const ta_cfg_t *cfg, size_t num) {
223+
Block *block = alloc_block(cfg, num);
233224
if (block != NULL) {
234225
return block->addr;
235226
}
@@ -272,12 +263,12 @@ static void memcopy(void *dst, void *src, size_t num) {
272263
}
273264
#endif
274265

275-
void *ta_calloc(size_t num, size_t size) {
266+
void *ta_calloc(const ta_cfg_t *cfg, size_t num, size_t size) {
276267
size_t orig = num;
277268
num *= size;
278269
// check for overflow
279270
if (size == 0 || num / size == orig) {
280-
Block *block = alloc_block(num);
271+
Block *block = alloc_block(cfg, num);
281272
if (block != NULL) {
282273
memclear(block->addr, block->size);
283274
return block->addr;
@@ -289,10 +280,11 @@ void *ta_calloc(size_t num, size_t size) {
289280
return NULL;
290281
}
291282

292-
size_t ta_getsize(void *ptr) {
283+
size_t ta_getsize(const ta_cfg_t *cfg, void *ptr) {
293284
if (ptr == NULL) {
294285
return 0;
295286
}
287+
Heap *heap = (Heap *)cfg->base;
296288
Block *block = heap->used;
297289
while (block != NULL) {
298290
if (ptr == block->addr) {
@@ -303,24 +295,24 @@ size_t ta_getsize(void *ptr) {
303295
return 0;
304296
}
305297

306-
void *ta_realloc(void *ptr, size_t num) {
298+
void *ta_realloc(const ta_cfg_t *cfg, void *ptr, size_t num) {
307299
if (ptr == NULL) {
308-
return ta_alloc(num);
300+
return ta_alloc(cfg, num);
309301
} else if (num == 0) {
310-
ta_free(ptr);
302+
ta_free(cfg, ptr);
311303
return NULL;
312304
}
313-
size_t size = ta_getsize(ptr);
314-
if (num <= size && size - num <= heap_split_thresh) {
305+
size_t size = ta_getsize(cfg, ptr);
306+
if (num <= size && size - num <= cfg->split_thresh) {
315307
return ptr; // keep current block
316308
}
317-
Block *block = alloc_block(num);
309+
Block *block = alloc_block(cfg, num);
318310
if (block != NULL) {
319311
if (size > num) {
320312
size = num;
321313
}
322314
memcopy(block->addr, ptr, size);
323-
ta_free(ptr);
315+
ta_free(cfg, ptr);
324316
return block->addr;
325317
}
326318
#ifdef TA_USE_STDLIB
@@ -338,18 +330,22 @@ static size_t count_blocks(Block *ptr) {
338330
return num;
339331
}
340332

341-
size_t ta_num_free() {
333+
size_t ta_num_free(const ta_cfg_t *cfg) {
334+
Heap *heap = (Heap *)cfg->base;
342335
return count_blocks(heap->free);
343336
}
344337

345-
size_t ta_num_used() {
338+
size_t ta_num_used(const ta_cfg_t *cfg) {
339+
Heap *heap = (Heap *)cfg->base;
346340
return count_blocks(heap->used);
347341
}
348342

349-
size_t ta_num_fresh() {
343+
size_t ta_num_fresh(const ta_cfg_t *cfg) {
344+
Heap *heap = (Heap *)cfg->base;
350345
return count_blocks(heap->fresh);
351346
}
352347

353-
bool ta_check() {
354-
return heap_max_blocks == ta_num_free() + ta_num_used() + ta_num_fresh();
348+
bool ta_check(const ta_cfg_t *cfg) {
349+
return cfg->max_blocks ==
350+
ta_num_free(cfg) + ta_num_used(cfg) + ta_num_fresh(cfg);
355351
}

tinyalloc.h

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@ extern "C" {
55
#include <stdbool.h>
66
#include <stddef.h>
77

8-
bool ta_init(const void *base, const void *limit, const size_t heap_blocks, const size_t split_thresh, const size_t alignment);
9-
void *ta_alloc(size_t num);
10-
void *ta_calloc(size_t num, size_t size);
11-
size_t ta_getsize(void *ptr);
12-
void *ta_realloc(void *ptr, size_t num);
13-
bool ta_free(void *ptr);
8+
typedef struct {
9+
void *base;
10+
void *limit;
11+
size_t max_blocks;
12+
size_t split_thresh;
13+
size_t alignment;
14+
} ta_cfg_t;
1415

15-
size_t ta_num_free();
16-
size_t ta_num_used();
17-
size_t ta_num_fresh();
18-
bool ta_check();
16+
void ta_init(const ta_cfg_t *cfg);
17+
void *ta_alloc(const ta_cfg_t *cfg, size_t num);
18+
void *ta_calloc(const ta_cfg_t *cfg, size_t num, size_t size);
19+
size_t ta_getsize(const ta_cfg_t *cfg, void *ptr);
20+
void *ta_realloc(const ta_cfg_t *cfg, void *ptr, size_t num);
21+
bool ta_free(const ta_cfg_t *cfg, void *ptr);
22+
23+
size_t ta_num_free(const ta_cfg_t *cfg);
24+
size_t ta_num_used(const ta_cfg_t *cfg);
25+
size_t ta_num_fresh(const ta_cfg_t *cfg);
26+
bool ta_check(const ta_cfg_t *cfg);
1927

2028
#ifdef __cplusplus
2129
}

0 commit comments

Comments
 (0)