toys

toys.git
git clone git://git.lenczewski.org/toys.git
Log | Files | Refs | README | LICENSE

allocators.c (6094B)


      1 #define HEADER_IMPL
      2 #include "allocators.h"
      3 
      4 #include <assert.h>
      5 #include <stdio.h>
      6 
      7 struct mystruct {
      8 	int a, b, c;
      9 };
     10 
     11 struct mystruct2 {
     12 	alignas(64) char buf[17];
     13 };
     14 
     15 static void
     16 test_arena(struct arena_allocator *allocator);
     17 
     18 static void
     19 test_stack(struct stack_allocator *allocator);
     20 
     21 static void
     22 test_pool(struct pool_allocator *allocator);
     23 
     24 static void
     25 test_freelist(struct freelist_allocator *allocator);
     26 
     27 static void
     28 test_buddy(struct buddy_allocator *allocator);
     29 
     30 int
     31 main(void)
     32 {
     33 	printf("IS_POW2(1): %d, IS_POW2(2): %d, IS_POW2(3): %d\n",
     34 			IS_POW2(1), IS_POW2(2), IS_POW2(3));
     35 
     36 	printf("IS_ALIGNED(2, 2): %d, IS_ALIGNED(1, 2): %d\n",
     37 			IS_ALIGNED(2, 2), IS_ALIGNED(1, 2));
     38 
     39 	printf("ALIGN_PREV(2, 2): %d, ALIGN_PREV(1, 2): %d\n",
     40 			ALIGN_PREV(2, 2), ALIGN_PREV(1, 2));
     41 
     42 	printf("ALIGN_NEXT(2, 2): %d, ALIGN_NEXT(1, 2): %d\n",
     43 			ALIGN_NEXT(2, 2), ALIGN_NEXT(1, 2));
     44 
     45 	char buf[1024];
     46 
     47 	struct arena_allocator arena = { .ptr = buf, .cap = sizeof buf, .len = 0, };
     48 	test_arena(&arena);
     49 
     50 	struct stack_allocator stack = { .ptr = buf, .cap = sizeof buf, .len = 0, };
     51 	test_stack(&stack);
     52 
     53 	struct pool_allocator pool = { .ptr = buf, .cap = sizeof buf, };
     54 	pool_allocator_init(&pool, pool.cap / 16);
     55 	test_pool(&pool);
     56 
     57 	struct freelist_allocator heap_freelist = { .ptr = buf, .cap = sizeof buf, };
     58 	freelist_allocator_init(&heap_freelist);
     59 	test_freelist(&heap_freelist);
     60 
     61 	struct buddy_allocator buddy = { .ptr = buf, .cap = sizeof buf, };
     62 	test_buddy(&buddy);
     63 
     64 	return 0;
     65 }
     66 
     67 static void
     68 test_arena(struct arena_allocator *allocator)
     69 {
     70 	printf("arena: buf: %p, cap: %zu, len: %zu\n",
     71 			allocator->ptr, allocator->cap, allocator->len);
     72 
     73 	struct mystruct *foo = arena_alloc(allocator, sizeof *foo, alignof(struct mystruct));
     74 	assert(foo);
     75 
     76 	printf("foo: %p, sizeof foo: %zu, alignof foo: %zu\n",
     77 			foo, sizeof *foo, alignof(struct mystruct));
     78 
     79 	foo->a = foo->b = foo->c = 42;
     80 
     81 	struct mystruct *bar = ARENA_ALLOC_SIZED(allocator, struct mystruct);
     82 	assert(bar);
     83 
     84 	printf("bar: %p, sizeof bar: %zu, alignof bar: %zu\n",
     85 			bar, sizeof *bar, alignof(struct mystruct));
     86 
     87 	bar->a = bar->b = bar->c = 69;
     88 
     89 	assert(foo != bar);
     90 
     91 	printf("arena_reset() ...\n");
     92 
     93 	printf("\tbefore reset: foo->a = %d\n", foo->a);
     94 	arena_reset(allocator);
     95 	printf("\tafter reset: foo->a = %d\n", foo->a);
     96 
     97 	struct mystruct *baz = ARENA_ALLOC_SIZED(allocator, struct mystruct);
     98 	assert(baz);
     99 	assert(foo == baz);
    100 
    101 	printf("\tafter reset: baz: %p, baz->a = %d, baz == foo: %d\n",
    102 			baz, baz->a, baz == foo);
    103 
    104 	// struct mystruct2 *fee = ARENA_ALLOC_ARRAY(allocator, struct mystruct2, 2);
    105 	struct mystruct2 *fee = arena_alloc(allocator, sizeof *fee * 2, alignof(struct mystruct2));
    106 	assert(fee);
    107 
    108 	printf("fee: %p, sizeof fee: %zu, alignof fee: %zu\n",
    109 			fee, sizeof *fee, alignof(struct mystruct2));
    110 
    111 	printf("fee[0]: %p, fee[0] is aligned: %d, fee[1]: %p, fee[1] is aligned: %d\n",
    112 			&fee[0], IS_ALIGNED((uintptr_t) &fee[0], alignof(struct mystruct2)),
    113 			&fee[1], IS_ALIGNED((uintptr_t) &fee[1], alignof(struct mystruct2)));
    114 
    115 	assert(IS_ALIGNED((uintptr_t) &fee[0], 64));
    116 	assert(IS_ALIGNED((uintptr_t) &fee[1], 64));
    117 
    118 	char *mybuf = arena_alloc(allocator, 128, 256);
    119 	assert(mybuf);
    120 
    121 	printf("mybuf: %p, sizeof mybuf: 128, alignof mybuf: 256\n", mybuf);
    122 
    123 	assert(IS_ALIGNED((uintptr_t) mybuf, 256));
    124 }
    125 
    126 static void
    127 test_stack(struct stack_allocator *allocator)
    128 {
    129 	printf("stack: buf: %p, cap: %zu, len: %zu\n",
    130 			allocator->ptr, allocator->cap, allocator->len);
    131 
    132 	struct mystruct *foo = stack_alloc(allocator, sizeof *foo, alignof(struct mystruct));
    133 	assert(foo);
    134 
    135 	printf("foo: %p, sizeof foo: %zu, alignof foo: %zu\n",
    136 			foo, sizeof *foo, alignof(struct mystruct));
    137 	printf("foo padding: %zu\n", stack_alloc_padding(foo));
    138 
    139 	stack_free(allocator, foo);
    140 
    141 	void *bar = stack_alloc(allocator, 64, 8);
    142 	printf("bar: %p, sizeof bar: %d, alignof bar: %d\n",
    143 			bar, 64, 8);
    144 	printf("bar padding: %zu\n", stack_alloc_padding(bar));
    145 
    146 	void *baz = stack_alloc(allocator, 8, 8);
    147 	printf("baz: %p, sizeof baz: %d, alignof baz: %d\n",
    148 			baz, 8, 8);
    149 	printf("baz padding: %zu\n", stack_alloc_padding(baz));
    150 
    151 	stack_free(allocator, bar);
    152 	assert(allocator->len == 0);
    153 
    154 	// WARN: freeing baz here is unsupported, and WILL cause memory leakage
    155 	// stack_free(allocator, baz);
    156 }
    157 
    158 static void
    159 test_pool(struct pool_allocator *allocator)
    160 {
    161 	printf("pool: buf: %p, cap: %zu, block_size: %zu\n",
    162 			allocator->ptr, allocator->cap, allocator->block_size);
    163 }
    164 
    165 static inline void
    166 freelist_print(struct freelist_allocator *allocator)
    167 {
    168 	printf("freelist_allocator.freelist:\n");
    169 
    170 	struct freelist_allocator_block *freelist = &allocator->freelist, *block;
    171 	for (block = freelist->next; block != freelist; block = block->next) {
    172 		printf("\t{ %p, prev: %p, next: %p, size: %zu }\n",
    173 				block, block->prev, block->next, block->size);
    174 	}
    175 }
    176 
    177 static void
    178 test_freelist(struct freelist_allocator *allocator)
    179 {
    180 	printf("heap freelist: buf: %p, cap: %zu\n",
    181 			allocator->ptr, allocator->cap);
    182 
    183 	struct mystruct *foo = freelist_alloc(allocator, sizeof *foo, alignof(struct mystruct));
    184 	assert(foo);
    185 
    186 	freelist_print(allocator);
    187 
    188 	freelist_free(allocator, foo);
    189 	assert(allocator->freelist.next->size == allocator->cap);
    190 
    191 	freelist_print(allocator);
    192 
    193 	struct mystruct *bar = freelist_alloc(allocator, sizeof *bar, alignof(struct mystruct));
    194 	freelist_print(allocator);
    195 	struct mystruct *baz = freelist_alloc(allocator, sizeof *baz, alignof(struct mystruct));
    196 	freelist_print(allocator);
    197 	struct mystruct *qux = freelist_alloc(allocator, sizeof *qux, alignof(struct mystruct));
    198 	freelist_print(allocator);
    199 
    200 	freelist_free(allocator, baz);
    201 	freelist_print(allocator);
    202 	freelist_free(allocator, qux);
    203 	freelist_print(allocator);
    204 
    205 	struct mystruct *fee = freelist_alloc(allocator, sizeof *fee, alignof(struct mystruct));
    206 	assert(fee == baz);
    207 
    208 	freelist_free(allocator, bar);
    209 	freelist_free(allocator, fee);
    210 
    211 	assert(allocator->freelist.next->size == allocator->cap);
    212 	freelist_print(allocator);
    213 }
    214 
    215 static void
    216 test_buddy(struct buddy_allocator *allocator)
    217 {
    218 	printf("buddy: buf: %p, cap: %zu\n",
    219 			allocator->ptr, allocator->cap);
    220 }