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 }