|
5 | 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
6 | 6 | */
|
7 | 7 |
|
8 |
| -#include <assert.h> |
| 8 | +/* A MT-safe base allocator */ |
9 | 9 |
|
| 10 | +#include "base_alloc_global.h" |
10 | 11 | #include "base_alloc.h"
|
| 12 | +#include "base_alloc_internal.h" |
| 13 | +#include "utils_math.h" |
11 | 14 |
|
12 |
| -#define SIZE_BA_POOL_CHUNK 128 |
| 15 | +#include <stdio.h> |
13 | 16 |
|
14 |
| -// global base allocator used by all providers and pools |
15 |
| -static umf_ba_pool_t *BA_pool = NULL; |
| 17 | +// allocation classes need to be powers of 2 |
| 18 | +#define ALLOCATION_CLASSES \ |
| 19 | + { 16, 32, 64, 128 } |
| 20 | +#define NUM_ALLOCATION_CLASSES 4 |
16 | 21 |
|
17 |
| -int umf_ba_create_global(void) { |
18 |
| - assert(BA_pool == NULL); |
| 22 | +struct base_alloc_t { |
| 23 | + size_t ac_sizes[NUM_ALLOCATION_CLASSES]; |
| 24 | + umf_ba_pool_t *ac[NUM_ALLOCATION_CLASSES]; |
| 25 | +}; |
19 | 26 |
|
20 |
| - BA_pool = umf_ba_create(SIZE_BA_POOL_CHUNK); |
21 |
| - if (!BA_pool) { |
22 |
| - return -1; |
| 27 | +static struct base_alloc_t BASE_ALLOC = {.ac_sizes = ALLOCATION_CLASSES}; |
| 28 | +static size_t SMALLEST_AC_SIZE_LOG2 = 0; |
| 29 | + |
| 30 | +void umf_ba_create_global(void) { |
| 31 | + for (int i = 0; i < NUM_ALLOCATION_CLASSES; i++) { |
| 32 | + // allocation classes need to be powers of 2 |
| 33 | + assert(0 == (BASE_ALLOC.ac_sizes[i] & (BASE_ALLOC.ac_sizes[i] - 1))); |
| 34 | + BASE_ALLOC.ac[i] = umf_ba_create(BASE_ALLOC.ac_sizes[i]); |
| 35 | + if (!BASE_ALLOC.ac[i]) { |
| 36 | + fprintf(stderr, |
| 37 | + "Cannot create base alloc allocation class for size: %zu\n", |
| 38 | + BASE_ALLOC.ac_sizes[i]); |
| 39 | + } |
23 | 40 | }
|
24 | 41 |
|
25 |
| - return 0; |
| 42 | + size_t smallestSize = BASE_ALLOC.ac_sizes[0]; |
| 43 | + SMALLEST_AC_SIZE_LOG2 = log2Utils(smallestSize); |
26 | 44 | }
|
27 | 45 |
|
28 | 46 | void umf_ba_destroy_global(void) {
|
29 |
| - assert(BA_pool); |
30 |
| - umf_ba_destroy(BA_pool); |
31 |
| - BA_pool = NULL; |
| 47 | + for (int i = 0; i < NUM_ALLOCATION_CLASSES; i++) { |
| 48 | + if (BASE_ALLOC.ac[i]) { |
| 49 | + umf_ba_destroy(BASE_ALLOC.ac[i]); |
| 50 | + } |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +static int size_to_idx(size_t size) { |
| 55 | + assert(size <= BASE_ALLOC.ac_sizes[NUM_ALLOCATION_CLASSES - 1]); |
| 56 | + |
| 57 | + if (size <= BASE_ALLOC.ac_sizes[0]) { |
| 58 | + return 0; |
| 59 | + } |
| 60 | + |
| 61 | + int isPowerOf2 = (0 == (size & (size - 1))); |
| 62 | + int index = (int)(log2Utils(size) + !isPowerOf2 - SMALLEST_AC_SIZE_LOG2); |
| 63 | + |
| 64 | + assert(index >= 0); |
| 65 | + assert(index < NUM_ALLOCATION_CLASSES); |
| 66 | + |
| 67 | + return index; |
| 68 | +} |
| 69 | + |
| 70 | +void *umf_ba_global_alloc(size_t size) { |
| 71 | + if (size > BASE_ALLOC.ac_sizes[NUM_ALLOCATION_CLASSES - 1]) { |
| 72 | + return ba_os_alloc(size); |
| 73 | + } |
| 74 | + |
| 75 | + int ac_index = size_to_idx(size); |
| 76 | + if (!BASE_ALLOC.ac[ac_index]) { |
| 77 | + // if creating ac failed, fall back to os allocation |
| 78 | + return ba_os_alloc(size); |
| 79 | + } |
| 80 | + |
| 81 | + return umf_ba_alloc(BASE_ALLOC.ac[ac_index]); |
32 | 82 | }
|
33 | 83 |
|
34 |
| -umf_ba_pool_t *umf_ba_get_pool(size_t size) { |
35 |
| - // TODO: a specific class-size base allocator can be returned here |
36 |
| - assert(BA_pool); |
37 |
| - assert(size <= SIZE_BA_POOL_CHUNK); |
| 84 | +void umf_ba_global_free(void *ptr, size_t size) { |
| 85 | + if (size > BASE_ALLOC.ac_sizes[NUM_ALLOCATION_CLASSES - 1]) { |
| 86 | + ba_os_free(ptr, size); |
| 87 | + return; |
| 88 | + } |
38 | 89 |
|
39 |
| - if (size > SIZE_BA_POOL_CHUNK) { |
40 |
| - return NULL; |
| 90 | + int ac_index = size_to_idx(size); |
| 91 | + if (!BASE_ALLOC.ac[ac_index]) { |
| 92 | + // if creating ac failed, memory must have been allocated by os |
| 93 | + ba_os_free(ptr, size); |
| 94 | + return; |
41 | 95 | }
|
42 | 96 |
|
43 |
| - return BA_pool; |
| 97 | + umf_ba_free(BASE_ALLOC.ac[ac_index], ptr); |
44 | 98 | }
|
0 commit comments