@cryptotaxi247 / netdata-1 / commits / a6da6beb7

array allocator for dbengine page descriptors (#13312)

* array allocator for dbengine page descriptors * full implementation of array allocator with cleanup * faster deallocations * eliminate entierely the need for loops during free * addressed comments * lower the min number of elements to 10

Costa Tsaousis committed Jul 8, 2022 at 00:09 UTC a6da6beb71f31ed5e89d9ed7a5a7d3242cdd8d8e
14 files changed +461 -9
CMakeLists.txt
+2
@@ -370,6 +370,8 @@ set(LIBNETDATA_FILES
370 libnetdata/adaptive_resortable_list/adaptive_resortable_list.h
371 libnetdata/config/appconfig.c
372 libnetdata/config/appconfig.h
373 + libnetdata/arrayalloc/arrayalloc.c
374 + libnetdata/arrayalloc/arrayalloc.h
375 libnetdata/avl/avl.c
376 libnetdata/avl/avl.h
377 libnetdata/buffer/buffer.c
Makefile.am
+2
@@ -136,6 +136,8 @@ LIBNETDATA_FILES = \
136 libnetdata/adaptive_resortable_list/adaptive_resortable_list.h \
137 libnetdata/config/appconfig.c \
138 libnetdata/config/appconfig.h \
139 + libnetdata/arrayalloc/arrayalloc.c \
140 + libnetdata/arrayalloc/arrayalloc.h \
141 libnetdata/avl/avl.c \
142 libnetdata/avl/avl.h \
143 libnetdata/buffer/buffer.c \
configure.ac
+1
@@ -1724,6 +1724,7 @@ AC_CONFIG_FILES([
1724 libnetdata/Makefile
1725 libnetdata/tests/Makefile
1726 libnetdata/adaptive_resortable_list/Makefile
1727 + libnetdata/arrayalloc/Makefile
1728 libnetdata/avl/Makefile
1729 libnetdata/buffer/Makefile
1730 libnetdata/clocks/Makefile
database/engine/pagecache.c
+47 -3
@@ -3,6 +3,50 @@
3
4 #include "rrdengine.h"
5
6 +ARAL page_descr_aral = {
7 + .element_size = sizeof(struct rrdeng_page_descr),
8 + .elements = 20000,
9 + .filename = "page_descriptors",
10 + .cache_dir = &netdata_configured_cache_dir,
11 + .use_mmap = false,
12 + .internal.initialized = false
13 +};
14 +
15 +void rrdeng_page_descr_aral_go_singlethreaded(void) {
16 + page_descr_aral.internal.lockless = true;
17 +}
18 +void rrdeng_page_descr_aral_go_multithreaded(void) {
19 + page_descr_aral.internal.lockless = false;
20 +}
21 +
22 +struct rrdeng_page_descr *rrdeng_page_descr_mallocz(void) {
23 + struct rrdeng_page_descr *descr;
24 + descr = arrayalloc_mallocz(&page_descr_aral);
25 + return descr;
26 +}
27 +
28 +void rrdeng_page_descr_freez(struct rrdeng_page_descr *descr) {
29 + arrayalloc_freez(&page_descr_aral, descr);
30 +}
31 +
32 +void rrdeng_page_descr_use_malloc(void) {
33 + if(page_descr_aral.internal.initialized)
34 + error("DBENGINE: cannot change ARAL allocation policy after it has been initialized.");
35 + else
36 + page_descr_aral.use_mmap = false;
37 +}
38 +
39 +void rrdeng_page_descr_use_mmap(void) {
40 + if(page_descr_aral.internal.initialized)
41 + error("DBENGINE: cannot change ARAL allocation policy after it has been initialized.");
42 + else
43 + page_descr_aral.use_mmap = true;
44 +}
45 +
46 +bool rrdeng_page_descr_is_mmap(void) {
47 + return page_descr_aral.use_mmap;
48 +}
49 +
50 /* Forward declarations */
51 static int pg_cache_try_evict_one_page_unsafe(struct rrdengine_instance *ctx);
52
@@ -81,7 +125,7 @@ struct rrdeng_page_descr *pg_cache_create_descr(void)
125 {
126 struct rrdeng_page_descr *descr;
127
84 - descr = mallocz(sizeof(*descr));
128 + descr = rrdeng_page_descr_mallocz();
129 descr->page_length = 0;
130 descr->start_time = INVALID_TIME;
131 descr->end_time = INVALID_TIME;
@@ -494,7 +538,7 @@ uint8_t pg_cache_punch_hole(struct rrdengine_instance *ctx, struct rrdeng_page_d
538 (void)sleep_usec(1000); /* 1 msec */
539 }
540 destroy:
497 - freez(descr);
541 + rrdeng_page_descr_freez(descr);
542 pg_cache_update_metric_times(page_index);
543
544 return can_delete_metric;
@@ -1312,7 +1356,7 @@ void free_page_cache(struct rrdengine_instance *ctx)
1356 else
1357 metric_single_point_pages++;
1358
1315 - freez(descr);
1359 + rrdeng_page_descr_freez(descr);
1360 pages_bytes += sizeof(*descr);
1361 pages_number++;
1362
database/engine/pagecache.h
+8
@@ -195,6 +195,14 @@ extern unsigned long pg_cache_hard_limit(struct rrdengine_instance *ctx);
195 extern unsigned long pg_cache_soft_limit(struct rrdengine_instance *ctx);
196 extern unsigned long pg_cache_committed_hard_limit(struct rrdengine_instance *ctx);
197
198 +extern void rrdeng_page_descr_aral_go_singlethreaded(void);
199 +extern void rrdeng_page_descr_aral_go_multithreaded(void);
200 +extern void rrdeng_page_descr_use_malloc(void);
201 +extern void rrdeng_page_descr_use_mmap(void);
202 +extern bool rrdeng_page_descr_is_mmap(void);
203 +extern struct rrdeng_page_descr *rrdeng_page_descr_mallocz(void);
204 +extern void rrdeng_page_descr_freez(struct rrdeng_page_descr *descr);
205 +
206 static inline void
207 pg_cache_atomic_get_pg_info(struct rrdeng_page_descr *descr, usec_t *end_timep, uint32_t *page_lengthp)
208 {
database/engine/rrdengineapi.c
+1 -1
@@ -211,7 +211,7 @@ void rrdeng_store_metric_flush_current_page(STORAGE_COLLECT_HANDLE *collection_h
211 } else {
212 dbengine_page_free(descr->pg_cache_descr->page);
213 rrdeng_destroy_pg_cache_descr(ctx, descr->pg_cache_descr);
214 - freez(descr);
214 + rrdeng_page_descr_freez(descr);
215 }
216 handle->descr = NULL;
217 }
database/rrdhost.c
+9
@@ -768,6 +768,11 @@ int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
768 default_rrdeng_page_fetch_retries = 1;
769 config_set_number(CONFIG_SECTION_DB, "dbengine page fetch retries", default_rrdeng_page_fetch_retries);
770 }
771 +
772 + if(config_get_boolean(CONFIG_SECTION_DB, "dbengine page descriptors in file mapped memory", rrdeng_page_descr_is_mmap()) == CONFIG_BOOLEAN_YES)
773 + rrdeng_page_descr_use_mmap();
774 + else
775 + rrdeng_page_descr_use_malloc();
776 #endif
777
778 rrdset_free_obsolete_time = config_get_number(CONFIG_SECTION_DB, "cleanup obsolete charts after secs", rrdset_free_obsolete_time);
@@ -825,6 +830,8 @@ int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
830 }
831
832 #ifdef ENABLE_DBENGINE
833 + rrdeng_page_descr_aral_go_singlethreaded();
834 +
835 int created_tiers = 0;
836 char dbenginepath[FILENAME_MAX + 1];
837 char dbengineconfig[200 + 1];
@@ -905,6 +912,8 @@ int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
912 rrd_unlock();
913 fatal("DBENGINE: Failed to be initialized.");
914 }
915 +
916 + rrdeng_page_descr_aral_go_multithreaded();
917 #else
918 storage_tiers = config_get_number(CONFIG_SECTION_DB, "storage tiers", 1);
919 if(storage_tiers != 1) {
libnetdata/Makefile.am
+1
@@ -5,6 +5,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5
6 SUBDIRS = \
7 adaptive_resortable_list \
8 + arrayalloc \
9 avl \
10 buffer \
11 clocks \
libnetdata/arrayalloc/Makefile.am new
+8
@@ -0,0 +1,8 @@
1 +# SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +AUTOMAKE_OPTIONS = subdir-objects
4 +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5 +
6 +dist_noinst_DATA = \
7 + README.md \
8 + $(NULL)
libnetdata/arrayalloc/README.md new
+7
@@ -0,0 +1,7 @@
1 +<!--
2 +title: "Array Allocator"
3 +custom_edit_url: https://github.com/netdata/netdata/edit/master/libnetdata/arrayalloc/README.md
4 +-->
5 +
6 +# Array Allocator
7 +
libnetdata/arrayalloc/arrayalloc.c new
+334
@@ -0,0 +1,334 @@
1 +#include "../libnetdata.h"
2 +#include "arrayalloc.h"
3 +#include "daemon/common.h"
4 +
5 +// max file size
6 +#define ARAL_MAX_PAGE_SIZE_MMAP (1*1024*1024*1024)
7 +
8 +// max malloc size
9 +#define ARAL_MAX_PAGE_SIZE_MALLOC (10*1024*1024)
10 +
11 +typedef struct arrayalloc_free {
12 + size_t size;
13 + struct arrayalloc_page *page;
14 + struct arrayalloc_free *next;
15 +} ARAL_FREE;
16 +
17 +typedef struct arrayalloc_page {
18 + const char *filename;
19 + size_t size; // the total size of the page
20 + size_t used_elements; // the total number of used elements on this page
21 + uint8_t *data;
22 + ARAL_FREE *free_list;
23 + struct arrayalloc_page *prev; // the prev page on the list
24 + struct arrayalloc_page *next; // the next page on the list
25 +} ARAL_PAGE;
26 +
27 +#define ARAL_NATURAL_ALIGNMENT (sizeof(uintptr_t) * 2)
28 +static inline size_t natural_alignment(size_t size, size_t alignment) {
29 + if(unlikely(size % alignment))
30 + size = size + alignment - (size % alignment);
31 +
32 + return size;
33 +}
34 +
35 +static void arrayalloc_init(ARAL *ar) {
36 + static netdata_mutex_t mutex = NETDATA_MUTEX_INITIALIZER;
37 + netdata_mutex_lock(&mutex);
38 +
39 + if(!ar->internal.initialized) {
40 + netdata_mutex_init(&ar->internal.mutex);
41 +
42 + long int page_size = sysconf(_SC_PAGE_SIZE);
43 + if (unlikely(page_size == -1))
44 + ar->internal.natural_page_size = 4096;
45 + else
46 + ar->internal.natural_page_size = page_size;
47 +
48 + // we need to add a page pointer after the element
49 + // so, first align the element size to the pointer size
50 + ar->internal.element_size = natural_alignment(ar->element_size, sizeof(uintptr_t));
51 +
52 + // then add the size of a pointer to it
53 + ar->internal.element_size = ar->internal.element_size + sizeof(uintptr_t);
54 +
55 + // make sure it is at least what we need for an ARAL_FREE slot
56 + if (ar->internal.element_size < sizeof(ARAL_FREE))
57 + ar->internal.element_size = sizeof(ARAL_FREE);
58 +
59 + // and finally align it to the natural alignment
60 + ar->internal.element_size = natural_alignment(ar->element_size, ARAL_NATURAL_ALIGNMENT);
61 +
62 + // this is where we should write the pointer
63 + ar->internal.page_ptr_offset = ar->internal.element_size - sizeof(uintptr_t);
64 +
65 + if(ar->element_size + sizeof(uintptr_t) > ar->internal.element_size)
66 + fatal("ARRAYALLOC: failed to calculate properly page_ptr_offset: element size %zu, sizeof(uintptr_t) %zu, natural alignment %zu, final element size %zu, page_ptr_offset %zu",
67 + ar->element_size, sizeof(uintptr_t), ARAL_NATURAL_ALIGNMENT, ar->internal.element_size, ar->internal.page_ptr_offset);
68 +
69 + //info("ARRAYALLOC: element size %zu, sizeof(uintptr_t) %zu, natural alignment %zu, final element size %zu, page_ptr_offset %zu",
70 + // ar->element_size, sizeof(uintptr_t), ARAL_NATURAL_ALIGNMENT, ar->internal.element_size, ar->internal.page_ptr_offset);
71 +
72 + if (ar->elements < 10)
73 + ar->elements = 10;
74 +
75 + ar->internal.mmap = (ar->use_mmap && ar->cache_dir && *ar->cache_dir) ? true : false;
76 + ar->internal.max_alloc_size = ar->internal.mmap ? ARAL_MAX_PAGE_SIZE_MMAP : ARAL_MAX_PAGE_SIZE_MALLOC;
77 +
78 + if(ar->internal.max_alloc_size % ar->internal.natural_page_size)
79 + ar->internal.max_alloc_size += ar->internal.natural_page_size - (ar->internal.max_alloc_size % ar->internal.natural_page_size) ;
80 +
81 + if(ar->internal.max_alloc_size % ar->internal.element_size)
82 + ar->internal.max_alloc_size -= ar->internal.max_alloc_size % ar->internal.element_size;
83 +
84 + ar->internal.first_page = NULL;
85 + ar->internal.last_page = NULL;
86 + ar->internal.allocation_multiplier = 1;
87 + ar->internal.file_number = 0;
88 +
89 + if(ar->internal.mmap) {
90 + char filename[FILENAME_MAX + 1];
91 + snprintfz(filename, FILENAME_MAX, "%s/array_alloc.mmap", *ar->cache_dir);
92 + int r = mkdir(filename, 0775);
93 + if (r != 0 && errno != EEXIST)
94 + fatal("Cannot create directory '%s'", filename);
95 + }
96 +
97 + ar->internal.initialized = true;
98 + }
99 +
100 + netdata_mutex_unlock(&mutex);
101 +}
102 +
103 +#ifdef NETDATA_INTERNAL_CHECKS
104 +static inline void arrayalloc_free_checks(ARAL *ar, ARAL_FREE *fr) {
105 + if(fr->size < ar->internal.element_size)
106 + fatal("ARRAYALLOC: free item of size %zu, less than the expected element size %zu", fr->size, ar->internal.element_size);
107 +
108 + if(fr->size % ar->internal.element_size)
109 + fatal("ARRAYALLOC: free item of size %zu is not multiple to element size %zu", fr->size, ar->internal.element_size);
110 +}
111 +#else
112 +#define arrayalloc_free_checks(ar, fr) debug_dummy()
113 +#endif
114 +
115 +static inline void unlink_page(ARAL *ar, ARAL_PAGE *page) {
116 + if(unlikely(!page)) return;
117 +
118 + if(page->next)
119 + page->next->prev = page->prev;
120 +
121 + if(page->prev)
122 + page->prev->next = page->next;
123 +
124 + if(page == ar->internal.first_page)
125 + ar->internal.first_page = page->next;
126 +
127 + if(page == ar->internal.last_page)
128 + ar->internal.last_page = page->prev;
129 +}
130 +
131 +static inline void link_page_first(ARAL *ar, ARAL_PAGE *page) {
132 + page->prev = NULL;
133 + page->next = ar->internal.first_page;
134 + if(page->next) page->next->prev = page;
135 +
136 + ar->internal.first_page = page;
137 +
138 + if(!ar->internal.last_page)
139 + ar->internal.last_page = page;
140 +}
141 +
142 +static inline void link_page_last(ARAL *ar, ARAL_PAGE *page) {
143 + page->next = NULL;
144 + page->prev = ar->internal.last_page;
145 + if(page->prev) page->prev->next = page;
146 +
147 + ar->internal.last_page = page;
148 +
149 + if(!ar->internal.first_page)
150 + ar->internal.first_page = page;
151 +}
152 +
153 +static inline ARAL_PAGE *find_page_with_allocation(ARAL *ar, void *ptr) {
154 + size_t seeking = (size_t)ptr;
155 + ARAL_PAGE *page;
156 +
157 + for(page = ar->internal.first_page; page ; page = page->next) {
158 + if(unlikely(seeking >= (size_t)page->data && seeking < (size_t)page->data + page->size))
159 + break;
160 + }
161 +
162 + return page;
163 +}
164 +
165 +static void arrayalloc_increase(ARAL *ar) {
166 + if(unlikely(!ar->internal.initialized))
167 + arrayalloc_init(ar);
168 +
169 + ARAL_PAGE *page = callocz(1, sizeof(ARAL_PAGE));
170 + page->size = ar->elements * ar->internal.element_size * ar->internal.allocation_multiplier;
171 + if(page->size > ar->internal.max_alloc_size)
172 + page->size = ar->internal.max_alloc_size;
173 + else
174 + ar->internal.allocation_multiplier *= 2;
175 +
176 + if(ar->internal.mmap) {
177 + ar->internal.file_number++;
178 + char filename[FILENAME_MAX + 1];
179 + snprintfz(filename, FILENAME_MAX, "%s/array_alloc.mmap/%s.%zu", *ar->cache_dir, ar->filename, ar->internal.file_number);
180 + page->filename = strdupz(filename);
181 + page->data = netdata_mmap(page->filename, page->size, MAP_SHARED, 0);
182 + if (unlikely(!page->data))
183 + fatal("Cannot allocate arrayalloc buffer of size %zu on filename '%s'", page->size, page->filename);
184 + }
185 + else
186 + page->data = mallocz(page->size);
187 +
188 + // link the free space to its page
189 + ARAL_FREE *fr = (ARAL_FREE *)page->data;
190 + fr->size = page->size;
191 + fr->page = page;
192 + fr->next = NULL;
193 + page->free_list = fr;
194 +
195 + // link the new page at the front of the list of pages
196 + link_page_first(ar, page);
197 +
198 + arrayalloc_free_checks(ar, fr);
199 +}
200 +
201 +static void arrayalloc_lock(ARAL *ar) {
202 + if(!ar->internal.lockless)
203 + netdata_mutex_lock(&ar->internal.mutex);
204 +}
205 +
206 +static void arrayalloc_unlock(ARAL *ar) {
207 + if(!ar->internal.lockless)
208 + netdata_mutex_unlock(&ar->internal.mutex);
209 +}
210 +
211 +ARAL *arrayalloc_create(size_t element_size, size_t elements, const char *filename, char **cache_dir) {
212 + ARAL *ar = callocz(1, sizeof(ARAL));
213 + ar->element_size = element_size;
214 + ar->elements = elements;
215 + ar->filename = filename;
216 + ar->cache_dir = cache_dir;
217 + return ar;
218 +}
219 +
220 +void *arrayalloc_mallocz(ARAL *ar) {
221 + arrayalloc_lock(ar);
222 +
223 + if(unlikely(!ar->internal.first_page || !ar->internal.first_page->free_list))
224 + arrayalloc_increase(ar);
225 +
226 + ARAL_PAGE *page = ar->internal.first_page;
227 + ARAL_FREE *fr = page->free_list;
228 +
229 + if(unlikely(!fr))
230 + fatal("ARRAYALLOC: free item cannot be NULL.");
231 +
232 + if(unlikely(fr->size < ar->internal.element_size))
233 + fatal("ARRAYALLOC: free item size %zu is smaller than %zu", fr->size, ar->internal.element_size);
234 +
235 + if(fr->size - ar->internal.element_size <= ar->internal.element_size) {
236 + // we are done with this page
237 + page->free_list = NULL;
238 +
239 + if(page != ar->internal.last_page) {
240 + unlink_page(ar, page);
241 + link_page_last(ar, page);
242 + }
243 + }
244 + else {
245 + uint8_t *data = (uint8_t *)fr;
246 + ARAL_FREE *fr2 = (ARAL_FREE *)&data[ar->internal.element_size];
247 + fr2->page = fr->page;
248 + fr2->size = fr->size - ar->internal.element_size;
249 + fr2->next = fr->next;
250 + page->free_list = fr2;
251 +
252 + arrayalloc_free_checks(ar, fr2);
253 + }
254 +
255 + fr->page->used_elements++;
256 +
257 + // put the page pointer after the element
258 + uint8_t *data = (uint8_t *)fr;
259 + ARAL_PAGE **page_ptr = (ARAL_PAGE **)&data[ar->internal.page_ptr_offset];
260 + *page_ptr = page;
261 +
262 + arrayalloc_unlock(ar);
263 + return (void *)fr;
264 +}
265 +
266 +void arrayalloc_freez(ARAL *ar, void *ptr) {
267 + if(!ptr) return;
268 + arrayalloc_lock(ar);
269 +
270 + // get the page pointer
271 + ARAL_PAGE *page;
272 + {
273 + uint8_t *data = (uint8_t *)ptr;
274 + ARAL_PAGE **page_ptr = (ARAL_PAGE **)&data[ar->internal.page_ptr_offset];
275 + page = *page_ptr;
276 +
277 +#ifdef NETDATA_INTERNAL_CHECKS
278 + // make it NULL so that we will fail on double free
279 + // do not enable this on production, because the MMAP file
280 + // will need to be saved again!
281 + *page_ptr = NULL;
282 +#endif
283 + }
284 +
285 +#ifdef NETDATA_INTERNAL_CHECKS
286 + {
287 + // find the page ptr belongs
288 + ARAL_PAGE *page2 = find_page_with_allocation(ar, ptr);
289 +
290 + if(unlikely(page != page2))
291 + fatal("ARRAYALLOC: page pointers do not match!");
292 +
293 + if (unlikely(!page2))
294 + fatal("ARRAYALLOC: free of pointer %p is not in arrayalloc address space.", ptr);
295 + }
296 +#endif
297 +
298 + if(unlikely(!page))
299 + fatal("ARRAYALLOC: possible corruption or double free of pointer %p", ptr);
300 +
301 + if (unlikely(!page->used_elements))
302 + fatal("ARRAYALLOC: free of pointer %p is inside a page without any active allocations.", ptr);
303 +
304 + page->used_elements--;
305 +
306 + // make this element available
307 + ARAL_FREE *fr = (ARAL_FREE *)ptr;
308 + fr->page = page;
309 + fr->size = ar->internal.element_size;
310 + fr->next = page->free_list;
311 + page->free_list = fr;
312 +
313 + // if the page is empty, release it
314 + if(!page->used_elements) {
315 + unlink_page(ar, page);
316 +
317 + // free it
318 + if(ar->internal.mmap) {
319 + munmap(page->data, page->size);
320 + unlink(page->filename);
321 + freez((void *)page->filename);
322 + }
323 + else
324 + freez(page->data);
325 +
326 + freez(page);
327 + }
328 + else if(page != ar->internal.first_page) {
329 + unlink_page(ar, page);
330 + link_page_first(ar, page);
331 + }
332 +
333 + arrayalloc_unlock(ar);
334 +}
libnetdata/arrayalloc/arrayalloc.h new
+35
@@ -0,0 +1,35 @@
1 +
2 +#ifndef ARRAYALLOC_H
3 +#define ARRAYALLOC_H 1
4 +
5 +#include "../libnetdata.h"
6 +
7 +typedef struct arrayalloc {
8 + size_t element_size;
9 + size_t elements;
10 + const char *filename;
11 + char **cache_dir;
12 + bool use_mmap;
13 +
14 + // private members - do not touch
15 + struct {
16 + bool mmap;
17 + bool lockless;
18 + bool initialized;
19 + size_t element_size;
20 + size_t page_ptr_offset;
21 + size_t file_number;
22 + size_t natural_page_size;
23 + size_t allocation_multiplier;
24 + size_t max_alloc_size;
25 + netdata_mutex_t mutex;
26 + struct arrayalloc_page *first_page;
27 + struct arrayalloc_page *last_page;
28 + } internal;
29 +} ARAL;
30 +
31 +extern ARAL *arrayalloc_create(size_t element_size, size_t elements, const char *filename, char **cache_dir);
32 +extern void *arrayalloc_mallocz(ARAL *ar);
33 +extern void arrayalloc_freez(ARAL *ar, void *ptr);
34 +
35 +#endif // ARRAYALLOC_H
libnetdata/libnetdata.h
+1
@@ -345,6 +345,7 @@ extern char *netdata_configured_host_prefix;
345 #include "json/json.h"
346 #include "health/health.h"
347 #include "string/utf8.h"
348 +#include "arrayalloc/arrayalloc.h"
349 #include "onewayalloc/onewayalloc.h"
350 #include "worker_utilization/worker_utilization.h"
351
libnetdata/onewayalloc/onewayalloc.c
+5 -5
@@ -1,9 +1,7 @@
1 #include "onewayalloc.h"
2
3 -static size_t OWA_NATURAL_PAGE_SIZE = 0;
4 -
3 // https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html
6 -#define OWA_NATURAL_ALIGNMENT (sizeof(void *) * 2)
4 +#define OWA_NATURAL_ALIGNMENT (sizeof(uintptr_t) * 2)
5
6 typedef struct owa_page {
7 size_t stats_pages;
@@ -30,6 +28,8 @@ static inline size_t natural_alignment(size_t size) {
28 // any number of times, for any amount of memory.
29
30 static OWA_PAGE *onewayalloc_create_internal(OWA_PAGE *head, size_t size_hint) {
31 + static size_t OWA_NATURAL_PAGE_SIZE = 0;
32 +
33 if(unlikely(!OWA_NATURAL_PAGE_SIZE)) {
34 long int page_size = sysconf(_SC_PAGE_SIZE);
35 if (unlikely(page_size == -1))
@@ -82,11 +82,11 @@ static OWA_PAGE *onewayalloc_create_internal(OWA_PAGE *head, size_t size_hint) {
82 head->stats_pages++;
83 head->stats_pages_size += size;
84
85 - return (ONEWAYALLOC *)page;
85 + return page;
86 }
87
88 ONEWAYALLOC *onewayalloc_create(size_t size_hint) {
89 - return onewayalloc_create_internal(NULL, size_hint);
89 + return (ONEWAYALLOC *)onewayalloc_create_internal(NULL, size_hint);
90 }
91
92 void *onewayalloc_mallocz(ONEWAYALLOC *owa, size_t size) {