Skip to content

Commit 9cab682

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 ccdaa00 commit 9cab682

File tree

2 files changed

+64
-59
lines changed

2 files changed

+64
-59
lines changed

tinyalloc.c

Lines changed: 46 additions & 49 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,17 +154,19 @@ 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;
171162
size_t orig = num;
172-
num = (num + heap_alignment - 1) & -heap_alignment;
163+
num = (num + cfg->alignment - 1) & -cfg->alignment;
173164
if (num < orig) {
174165
return NULL; // overflow
175166
}
176167
while (ptr != NULL) {
177-
const int is_top = ((size_t)ptr->addr + ptr->size >= top) && ((size_t)ptr->addr + num <= (size_t)heap_limit);
168+
const int is_top = ((size_t)ptr->addr + ptr->size >= top) &&
169+
((size_t)ptr->addr + num <= (size_t)cfg->limit);
178170
if (is_top || ptr->size >= num) {
179171
if (prev != NULL) {
180172
prev->next = ptr->next;
@@ -190,17 +182,17 @@ static Block *alloc_block(size_t num) {
190182
#ifndef TA_DISABLE_SPLIT
191183
} else if (heap->fresh != NULL) {
192184
size_t excess = ptr->size - num;
193-
if (excess >= heap_split_thresh) {
185+
if (excess >= cfg->split_thresh) {
194186
ptr->size = num;
195187
Block *split = heap->fresh;
196188
heap->fresh = split->next;
197189
split->addr = (void *)((size_t)ptr->addr + num);
198190
print_s("split");
199191
print_i((size_t)split->addr);
200192
split->size = excess;
201-
insert_block(split);
193+
insert_block(heap, split);
202194
#ifndef TA_DISABLE_COMPACT
203-
compact();
195+
compact(heap);
204196
#endif
205197
}
206198
#endif
@@ -213,7 +205,7 @@ static Block *alloc_block(size_t num) {
213205
// no matching free blocks
214206
// see if any other blocks available
215207
size_t new_top = top + num;
216-
if (heap->fresh != NULL && new_top <= (size_t)heap_limit) {
208+
if (heap->fresh != NULL && new_top <= (size_t)cfg->limit) {
217209
ptr = heap->fresh;
218210
heap->fresh = ptr->next;
219211
ptr->addr = (void *)top;
@@ -226,8 +218,8 @@ static Block *alloc_block(size_t num) {
226218
return NULL;
227219
}
228220

229-
void *ta_alloc(size_t num) {
230-
Block *block = alloc_block(num);
221+
void *ta_alloc(const ta_cfg_t *cfg, size_t num) {
222+
Block *block = alloc_block(cfg, num);
231223
if (block != NULL) {
232224
return block->addr;
233225
}
@@ -254,13 +246,13 @@ static void memclear(void *ptr, size_t num) {
254246
}
255247
#endif
256248

257-
void *ta_calloc(size_t num, size_t size) {
249+
void *ta_calloc(const ta_cfg_t *cfg, size_t num, size_t size) {
258250
size_t orig = num;
259251
num *= size;
260252
if (size != 0 && num / size != orig) {
261253
goto overflow;
262254
}
263-
Block *block = alloc_block(num);
255+
Block *block = alloc_block(cfg, num);
264256
if (block != NULL) {
265257
memclear(block->addr, block->size);
266258
return block->addr;
@@ -281,26 +273,31 @@ static size_t count_blocks(Block *ptr) {
281273
return num;
282274
}
283275

284-
size_t ta_num_free() {
276+
size_t ta_num_free(const ta_cfg_t *cfg) {
277+
Heap *heap = (Heap *)cfg->base;
285278
return count_blocks(heap->free);
286279
}
287280

288-
size_t ta_num_used() {
281+
size_t ta_num_used(const ta_cfg_t *cfg) {
282+
Heap *heap = (Heap *)cfg->base;
289283
return count_blocks(heap->used);
290284
}
291285

292-
size_t ta_num_fresh() {
286+
size_t ta_num_fresh(const ta_cfg_t *cfg) {
287+
Heap *heap = (Heap *)cfg->base;
293288
return count_blocks(heap->fresh);
294289
}
295290

296-
bool ta_check() {
297-
return heap_max_blocks == ta_num_free() + ta_num_used() + ta_num_fresh();
291+
bool ta_check(const ta_cfg_t *cfg) {
292+
return cfg->max_blocks ==
293+
ta_num_free(cfg) + ta_num_used(cfg) + ta_num_fresh(cfg);
298294
}
299295

300-
size_t ta_getsize(void *ptr) {
296+
size_t ta_getsize(const ta_cfg_t *cfg, void *ptr) {
301297
if (ptr == NULL) {
302298
return 0;
303299
}
300+
Heap *heap = (Heap *)cfg->base;
304301
Block *block = heap->used;
305302
while (block != NULL) {
306303
if (ptr == block->addr) {
@@ -313,21 +310,21 @@ size_t ta_getsize(void *ptr) {
313310

314311
/* requires memcpy() */
315312
#ifdef TA_USE_STDLIB
316-
void *ta_realloc(void *ptr, size_t num) {
313+
void *ta_realloc(const ta_cfg_t *cfg, void *ptr, size_t num) {
317314
if (ptr == NULL) {
318-
return ta_alloc(num);
315+
return ta_alloc(cfg, num);
319316
} else if (num == 0) {
320-
ta_free(ptr);
317+
ta_free(cfg, ptr);
321318
return NULL;
322319
}
323-
size_t size = ta_getsize(ptr);
324-
Block *block = alloc_block(num);
320+
size_t size = ta_getsize(cfg, ptr);
321+
Block *block = alloc_block(cfg, num);
325322
if (block != NULL) {
326323
if (size > num) {
327324
size = num;
328325
}
329326
memcpy(block->addr, ptr, size);
330-
ta_free(ptr);
327+
ta_free(cfg, ptr);
331328
return block->addr;
332329
}
333330
errno = ENOMEM;

tinyalloc.h

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,29 @@ 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-
bool ta_free(void *ptr);
12-
size_t ta_getsize(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;
15+
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+
bool ta_free(const ta_cfg_t *cfg, void *ptr);
20+
size_t ta_getsize(const ta_cfg_t *cfg, void *ptr);
1321

1422
/* requires memcpy() */
1523
#ifdef TA_USE_STDLIB
16-
void *ta_realloc(void *ptr, size_t num);
24+
void *ta_realloc(const ta_cfg_t *cfg, void *ptr, size_t num);
1725
#endif
1826

19-
size_t ta_num_free();
20-
size_t ta_num_used();
21-
size_t ta_num_fresh();
22-
bool ta_check();
27+
size_t ta_num_free(const ta_cfg_t *cfg);
28+
size_t ta_num_used(const ta_cfg_t *cfg);
29+
size_t ta_num_fresh(const ta_cfg_t *cfg);
30+
bool ta_check(const ta_cfg_t *cfg);
2331

2432
#ifdef __cplusplus
2533
}

0 commit comments

Comments
 (0)