koliseo 0.6.4
Loading...
Searching...
No Matches
koliseo.c
Go to the documentation of this file.
1// jgabaut @ github.com/jgabaut
2// SPDX-License-Identifier: GPL-3.0-only
3/*
4 Copyright (C) 2023-2026 jgabaut
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18#ifndef _WIN32
19#ifndef _POSIX_C_SOURCE
20#define _POSIX_C_SOURCE 200809L
21#endif
22#endif
23#include "koliseo.h"
24
26 .collect_stats = 0,
27 .verbose_lvl = 0,
28 .block_while_has_temp = 1,
29 .allow_zerocount_push = 0,
30 .log_fp = NULL,
31 .growable = 0,
32 .log_filepath = "",
33 .err_handlers = {
34#ifndef KOLISEO_HAS_LOCATE
35 .OOM_handler = &KLS_OOM_default_handler__,
36 .PTRDIFF_MAX_handler = &KLS_PTRDIFF_MAX_default_handler__,
37 .ZEROCOUNT_handler = &KLS_ZEROCOUNT_default_handler__,
38#else
39 .OOM_handler = &KLS_OOM_default_handler_dbg__,
40 .PTRDIFF_MAX_handler = &KLS_PTRDIFF_MAX_default_handler_dbg__,
41 .ZEROCOUNT_handler = &KLS_ZEROCOUNT_default_handler_dbg__,
42#endif // KOLISEO_HAS_LOCATE
43 },
44};
45
47 .tot_pushes = 0,
48 .tot_temp_pushes = 0,
49 .tot_pops = 0,
50 .tot_temp_pops = 0,
51 .tot_logcalls = 0,
52#ifdef KLS_DEBUG_CORE
53 .worst_pushcall_time = -1,
54#endif
55};
56
57static bool kls_set_conf(Koliseo * kls, KLS_Conf conf); //Declare function used internally by kls_new() and kls_new_conf()
58
63const char *string_koliseo_version(void)
64{
65 return KOLISEO_API_VERSION_STRING;
66}
67
73{
74 return KOLISEO_API_VERSION_INT;
75}
76
77#if defined(__SANITIZE_ADDRESS__)
78#include <sanitizer/asan_interface.h>
79#define KLS_ASAN_POISON(addr, size) __asan_poison_memory_region((addr), (size))
80#define KLS_ASAN_UNPOISON(addr, size) __asan_unpoison_memory_region((addr), (size))
81#else
82#define KLS_ASAN_POISON(addr, size) ((void)0)
83#define KLS_ASAN_UNPOISON(addr, size) ((void)0)
84#endif // __SANITIZE_ADDRESS__
85
95#ifndef KOLISEO_HAS_LOCATE
96void KLS_OOM_default_handler__(Koliseo* kls, ptrdiff_t available, ptrdiff_t padding, ptrdiff_t size, ptrdiff_t count)
97#else
98void KLS_OOM_default_handler_dbg__(Koliseo* kls, ptrdiff_t available, ptrdiff_t padding, ptrdiff_t size, ptrdiff_t count, Koliseo_Loc loc)
99#endif // KOLISEO_HAS_LOCATE
100{
101#ifndef KOLISEO_HAS_LOCATE
102 fprintf(stderr,
103 "[KLS] Out of memory. size*count [%td] was bigger than available-padding [%td].\n",
104 size * count, available - padding);
105#else
106 fprintf(stderr,
107 "[KLS] " KLS_Loc_Fmt "Out of memory. size*count [%td] was bigger than available-padding [%td].\n",
108 KLS_Loc_Arg(loc),
109 size * count, available - padding);
110#endif // KOLISEO_HAS_LOCATE
111 kls_free(kls); // Is it even worth it to try?
112 exit(EXIT_FAILURE); // Better than nothing. May change to return NULL instead? Requiring refactor of handler signature
113}
114
115#ifndef KOLISEO_HAS_LOCATE
116void KLS_PTRDIFF_MAX_default_handler__(struct Koliseo* kls, ptrdiff_t size, ptrdiff_t count)
117#else
118void KLS_PTRDIFF_MAX_default_handler_dbg__(struct Koliseo* kls, ptrdiff_t size, ptrdiff_t count, Koliseo_Loc loc)
119#endif
120{
121#ifndef _WIN32
122#ifndef KOLISEO_HAS_LOCATE
123 fprintf(stderr,
124 "[KLS] count [%td] was bigger than PTRDIFF_MAX/size [%li].\n",
125 count, PTRDIFF_MAX / size);
126#else
127 fprintf(stderr,
128 "[KLS] " KLS_Loc_Fmt "count [%td] was bigger than PTRDIFF_MAX/size [%li].\n",
129 KLS_Loc_Arg(loc),
130 count, PTRDIFF_MAX / size);
131#endif // KOLISEO_HAS_LOCATE
132#else
133#ifndef KOLISEO_HAS_LOCATE
134 fprintf(stderr,
135 "[KLS] count [%td] was bigger than PTRDIFF_MAX/size [%lli].\n",
136 count, PTRDIFF_MAX / size);
137#else
138 fprintf(stderr,
139 "[KLS] " KLS_Loc_Fmt "count [%td] was bigger than PTRDIFF_MAX/size [%lli].\n",
140 KLS_Loc_Arg(loc),
141 count, PTRDIFF_MAX / size);
142#endif // KOLISEO_HAS_LOCATE
143#endif // _WIN32
144 kls_free(kls);
145 exit(EXIT_FAILURE);
146}
147
157#ifndef KOLISEO_HAS_LOCATE
158void KLS_ZEROCOUNT_default_handler__(Koliseo* kls, ptrdiff_t available, ptrdiff_t padding, ptrdiff_t size)
159#else
160void KLS_ZEROCOUNT_default_handler_dbg__(Koliseo* kls, ptrdiff_t available, ptrdiff_t padding, ptrdiff_t size, Koliseo_Loc loc)
161#endif // KOLISEO_HAS_LOCATE
162{
163#ifndef KOLISEO_HAS_LOCATE
164 fprintf(stderr,
165 "[KLS] Doing a zero-count push. size [%td] padding [%td] available [%td].\n",
166 size, padding, available);
167#else
168 fprintf(stderr,
169 "[KLS] " KLS_Loc_Fmt "Doing a zero-count push. size [%td] padding [%td] available [%td].\n",
170 KLS_Loc_Arg(loc),
171 size, padding, available);
172#endif // KOLISEO_HAS_LOCATE
173 kls_free(kls);
174 exit(EXIT_FAILURE);
175}
176
182KLS_Conf kls_conf_init_handled(int collect_stats, int verbose_lvl, int block_while_has_temp, int allow_zerocount_push, int growable, FILE* log_fp, const char* log_filepath, KLS_Err_Handlers err_handlers)
183{
184 KLS_Conf res = {0};
185 res.collect_stats = collect_stats;
186 res.verbose_lvl = verbose_lvl;
187 res.block_while_has_temp = block_while_has_temp;
188 res.allow_zerocount_push = allow_zerocount_push;
189 res.growable = growable;
190 res.log_fp = log_fp;
191 res.log_filepath = log_filepath;
192
193 if (err_handlers.OOM_handler != NULL) {
194 res.err_handlers.OOM_handler = err_handlers.OOM_handler;
195 } else {
196#ifndef KOLISEO_HAS_LOCATE
198#else
199 res.err_handlers.OOM_handler = &KLS_OOM_default_handler_dbg__;
200#endif // KOLISEO_HAS_LOCATE
201 }
202
203 if (err_handlers.PTRDIFF_MAX_handler != NULL) {
205 } else {
206#ifndef KOLISEO_HAS_LOCATE
208#else
209 res.err_handlers.PTRDIFF_MAX_handler = &KLS_PTRDIFF_MAX_default_handler_dbg__;
210#endif // KOLISEO_HAS_LOCATE
211 }
212
213 if (err_handlers.ZEROCOUNT_handler != NULL) {
215 } else {
216#ifndef KOLISEO_HAS_LOCATE
218#else
219 res.err_handlers.ZEROCOUNT_handler = &KLS_ZEROCOUNT_default_handler_dbg__;
220#endif // KOLISEO_HAS_LOCATE
221 }
222
223 return res;
224}
225
230KLS_Conf kls_conf_init(int collect_stats, int verbose_lvl, int block_while_has_temp, int allow_zerocount_push, int growable, FILE* log_fp, const char* log_filepath)
231{
233 return kls_conf_init_handled(collect_stats, verbose_lvl, block_while_has_temp, allow_zerocount_push, growable, log_fp, log_filepath, err_handlers);
234}
235
240{
241#ifdef KOLISEO_HAS_LOCATE
242 bool kls_locate = true;
243#else
244 bool kls_locate = false;
245#endif
246#ifdef KLS_DEBUG_CORE
247 bool kls_debug = true;
248#else
249 bool kls_debug = false;
250#endif
251#ifdef KOLISEO_HAS_EXPER
252 bool kls_exper = true;
253#else
254 bool kls_exper = false;
255#endif
256 bool features[3] = {
257 [0] = kls_debug,
258 [1] = kls_locate,
259 [2] = kls_exper,
260 };
261 int total_enabled = 0;
262 for (int i=0; i<3; i++) {
263 if (features[i]) {
264 total_enabled += 1;
265 }
266 }
267 fprintf(stderr, "[KLS] Enabled features: {");
268 if (total_enabled == 0) {
269 fprintf(stderr, "none}\n");
270 return;
271 } else {
272 if (kls_debug) {
273 fprintf(stderr, "debug%s", (total_enabled > 1 ? ", " : ""));
274 total_enabled -= 1;
275 }
276 if (kls_locate) {
277 fprintf(stderr, "locate%s", (total_enabled > 1 ? ", " : ""));
278 total_enabled -= 1;
279 }
280 if (kls_exper) {
281 fprintf(stderr, "exper");
282 }
283 fprintf(stderr, "}\n");
284 }
285}
286
292ptrdiff_t kls_get_pos(const Koliseo *kls)
293{
294 return kls->offset;
295}
296
309#ifndef KOLISEO_HAS_LOCATE
310void* kls__handle_push_result(Koliseo* kls, KLS_Push_Result r, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t padding, const char* caller_name)
311#else
312void* kls__handle_push_result_dbg(Koliseo* kls, KLS_Push_Result r, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t padding, const char* caller_name, Koliseo_Loc loc)
313#endif
314{
315 if (!kls) return NULL;
316 Koliseo* current = kls;
317 while (current->next != NULL) {
318 current = current->next;
319 }
320 if (r.error) {
321 const ptrdiff_t available = current->size - current->offset;
322 switch (r.error) {
323 case KLS_PUSH_OK: {
324 return r.p;
325 }
326 break;
327 case KLS_PUSH_SIZE_LT1: {
328#ifndef KOLISEO_HAS_LOCATE
329 fprintf(stderr,
330 "[KLS] %s(): size [%td] was < 1.\n",
331 caller_name,
332 size);
333#else
334 fprintf(stderr,
335 "[KLS] " KLS_Loc_Fmt "%s(): size [%td] was < 1.\n",
336 KLS_Loc_Arg(loc),
337 caller_name,
338 size);
339#endif // KOLISEO_HAS_LOCATE
340 }
341 break;
342 case KLS_PUSH_ALIGN_LT1: {
343#ifndef KOLISEO_HAS_LOCATE
344 fprintf(stderr,
345 "[KLS] %s(): align [%td] was < 1.\n",
346 caller_name,
347 align);
348#else
349 fprintf(stderr,
350 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was < 1.\n",
351 KLS_Loc_Arg(loc),
352 caller_name,
353 align);
354#endif // KOLISEO_HAS_LOCATE
355 }
356 break;
358#ifndef KOLISEO_HAS_LOCATE
359 fprintf(stderr,
360 "[KLS] %s(): align [%td] was not a power of 2.\n",
361 caller_name,
362 align);
363#else
364 fprintf(stderr,
365 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was not a power of 2.\n",
366 KLS_Loc_Arg(loc),
367 caller_name,
368 align);
369#endif // KOLISEO_HAS_LOCATE
370 }
371 break;
373#ifndef KOLISEO_HAS_LOCATE
374 fprintf(stderr,
375 "[KLS] %s(): count [%td] was < 0.\n",
376 caller_name,
377 count);
378#else
379 fprintf(stderr,
380 "[KLS] " KLS_Loc_Fmt "%s(): count [%td] was < 0.\n",
381 KLS_Loc_Arg(loc),
382 caller_name,
383 count);
384#endif // KOLISEO_HAS_LOCATE
385 }
386 break;
387 case KLS_PUSH_ZEROCOUNT: {
388 if (current->conf.err_handlers.ZEROCOUNT_handler != NULL) {
389#ifndef KOLISEO_HAS_LOCATE
390 current->conf.err_handlers.ZEROCOUNT_handler(current, available, padding, size);
391#else
392 current->conf.err_handlers.ZEROCOUNT_handler(current, available, padding, size, loc);
393#endif // KOLISEO_HAS_LOCATE
394 } else {
395#ifndef KOLISEO_HAS_LOCATE
396 fprintf(stderr,
397 "[KLS] %s(): Doing a zero-count push. size [%td] padding [%td] available [%td].\n",
398 caller_name,
399 size, padding, available);
400#else
401 fprintf(stderr,
402 "[KLS] " KLS_Loc_Fmt "%s(): Doing a zero-count push. size [%td] padding [%td] available [%td].\n",
403 KLS_Loc_Arg(loc),
404 caller_name,
405 size, padding, available);
406#endif // KOLISEO_HAS_LOCATE
407 kls_free(kls);
408 exit(EXIT_FAILURE);
409 }
410 }
411 break;
413#ifndef KOLISEO_HAS_LOCATE
414 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo has an open Koliseo_Temp session.\n", caller_name);
415#else
416 fprintf(stderr, "[ERROR] " KLS_Loc_Fmt "[%s()]: Passed Koliseo has an open Koliseo_Temp session.\n", KLS_Loc_Arg(loc), caller_name);
417 kls_log(kls, "ERROR", KLS_Loc_Fmt "[%s()]: Passed Koliseo has an open Koliseo_Temp session.", KLS_Loc_Arg(loc), caller_name);
418 exit(EXIT_FAILURE);
419#endif // KOLISEO_HAS_LOCATE
420 }
421 break;
423 if (current->conf.err_handlers.PTRDIFF_MAX_handler != NULL) {
424#ifndef KOLISEO_HAS_LOCATE
425 current->conf.err_handlers.PTRDIFF_MAX_handler(current, size, count);
426#else
427 current->conf.err_handlers.PTRDIFF_MAX_handler(current, size, count, loc);
428#endif // KOLISEO_HAS_LOCATE
429 } else { // Let's keep this here for now? It's the original part before adding KLS_PTRDIFF_MAX_default_handler__()
430#ifndef _WIN32
431#ifndef KOLISEO_HAS_LOCATE
432 fprintf(stderr,
433 "[KLS] %s(): count [%td] was bigger than PTRDIFF_MAX/size [%li].\n",
434 caller_name,
435 count, PTRDIFF_MAX / size);
436#else
437 fprintf(stderr,
438 "[KLS] " KLS_Loc_Fmt "%s(): count [%td] was bigger than PTRDIFF_MAX/size [%li].\n",
439 KLS_Loc_Arg(loc),
440 caller_name,
441 count, PTRDIFF_MAX / size);
442#endif // KOLISEO_HAS_LOCATE
443#else
444#ifndef KOLISEO_HAS_LOCATE
445 fprintf(stderr,
446 "[KLS] %s(): count [%td] was bigger than PTRDIFF_MAX/size [%lli].\n",
447 caller_name,
448 count, PTRDIFF_MAX / size);
449#else
450 fprintf(stderr,
451 "[KLS] " KLS_Loc_Fmt "%s(): count [%td] was bigger than PTRDIFF_MAX/size [%lli].\n",
452 KLS_Loc_Arg(loc),
453 caller_name,
454 count, PTRDIFF_MAX / size);
455#endif // KOLISEO_HAS_LOCATE
456#endif // _WIN32
457 }
458 }
459 break;
460 case KLS_PUSH_OOM: {
461 if (current->conf.err_handlers.OOM_handler != NULL) {
462#ifndef KOLISEO_HAS_LOCATE
463 current->conf.err_handlers.OOM_handler(current, available, padding, size, count);
464#else
465 current->conf.err_handlers.OOM_handler(current, available, padding, size, count, loc);
466#endif // KOLISEO_HAS_LOCATE
467 } else { // Let's keep this here for now? It's the original part before adding KLS_OOM_default_handler__()
468#ifndef KOLISEO_HAS_LOCATE
469 fprintf(stderr,
470 "[KLS] %s(): Out of memory. size*count [%td] was bigger than available-padding [%td].\n",
471 caller_name,
472 size * count, available - padding);
473#else
474 fprintf(stderr,
475 "[KLS] " KLS_Loc_Fmt "%s(): Out of memory. size*count [%td] was bigger than available-padding [%td].\n",
476 KLS_Loc_Arg(loc),
477 caller_name,
478 size * count, available - padding);
479#endif // KOLISEO_HAS_LOCATE
480 }
481 }
482 break;
483 default: {
484 fprintf(stderr, "[KLS] %s(): unexpected error code [%i]\n", __func__, r.error);
485 return NULL;
486 }
487 break;
488 }
489 }
490 return r.p;
491}
492
499void kls_log(Koliseo *kls, const char *tag, const char *format, ...)
500{
501 if (kls == NULL) {
502 fprintf(stderr, "[KLS] %s(): Passed kls was NULL.\n", __func__);
503 return;
504 }
505 if (kls->conf.verbose_lvl > 0) {
506 va_list args;
507 FILE *fp = kls->conf.log_fp;
508 va_start(args, format);
509 if (fp == NULL) {
510 fprintf(stderr,
511 "[KLS] %s(): Failed opening file to print logs.\n",
512 __func__);
513 } else {
514 time_t now = time(0);
515 const struct tm *mytime = localtime(&now);
516 char timeheader[500];
517 if (strftime(timeheader, sizeof timeheader, "%X", mytime)) {
518 fprintf(fp, "[%-10.10s] [%s] [", tag, timeheader);
519 vfprintf(fp, format, args);
520 fprintf(fp, "]\n");
521 }
522 }
523 va_end(args);
524 }
525}
526
544#ifndef KOLISEO_HAS_LOCATE
545Koliseo *kls_new_alloc_ext(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Hooks ext_handlers, void* user)
546#else
547Koliseo *kls_new_alloc_ext_dbg(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Hooks ext_handlers, void* user, Koliseo_Loc loc)
548#endif // KOLISEO_HAS_LOCATE
549{
550 if (size < (ptrdiff_t)sizeof(Koliseo)) {
551#ifndef KOLISEO_HAS_LOCATE
552 fprintf(stderr,
553 "[ERROR] at %s(): invalid requested kls size (%td). Min accepted is: (%td).\n",
554 __func__, size, (ptrdiff_t)sizeof(Koliseo));
555#else
556 fprintf(stderr,
557 "[ERROR] " KLS_Loc_Fmt "%s(): invalid requested kls size (%td). Min accepted is: (%td).\n",
558 KLS_Loc_Arg(loc), __func__, size, (ptrdiff_t)sizeof(Koliseo));
559#endif // KOLISEO_HAS_LOCATE
560 //TODO Is it better to abort the program?
561 return NULL;
562 }
563 void *p = alloc_func(size);
564 if (p) {
565 //sprintf(msg,"Allocated (%li) for new KLS.",size);
566 //kls_log("KLS",msg);
567 char h_size[200];
568 kls_formatSize(size, h_size, sizeof(h_size));
569 Koliseo *kls = p;
570 kls->data = p;
571 kls->size = size;
572 kls->offset = sizeof(*kls);
573 kls->prev_offset = kls->offset;
574 kls->has_temp = 0;
575 kls->t_kls = NULL;
576 kls_set_conf(kls, KLS_DEFAULT_CONF);
578 kls->conf.log_fp = stderr;
579
580 KLS_ASAN_POISON(kls->data + kls->offset, kls->size - kls->offset);
581
582 kls->hooks = ext_handlers;
583 if (user) {
584 kls->extension_data = user;
585 } else {
586 kls->extension_data = NULL;
587 }
588 kls->free_func = free_func;
589 kls->next = NULL;
590#ifdef KLS_DEBUG_CORE
591 kls_log(kls, "KLS", "API Level { %i } -> Allocated (%s) for new KLS.",
592 int_koliseo_version(), h_size);
593 kls_log(kls, "KLS", "KLS offset: { %p }.", kls);
594 kls_log(kls, "KLS", "Allocation begin offset: { %p }.",
595 kls + kls->offset);
596#endif
597
598 if (kls->hooks.on_new_handler != NULL) {
599 // Call on_new extension
600 kls->hooks.on_new_handler(kls);
601 }
602 } else {
603#ifndef KOLISEO_HAS_LOCATE
604 fprintf(stderr, "[KLS] Failed %s() call.\n", __func__);
605#else
606 fprintf(stderr, "[KLS] " KLS_Loc_Fmt "Failed %s() call.\n", KLS_Loc_Arg(loc), __func__);
607#endif // KOLISEO_HAS_LOCATE
608 exit(EXIT_FAILURE);
609 }
610#ifdef KLS_DEBUG_CORE
611 Koliseo *kls_ref = p;
612 if (kls_ref->conf.verbose_lvl > 0) {
613 print_kls_2file(kls_ref->conf.log_fp, p);
614 }
615#endif
616 return p;
617}
618
634#ifndef KOLISEO_HAS_LOCATE
635Koliseo *kls_new_alloc(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func)
636#else
637Koliseo *kls_new_alloc_dbg(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, Koliseo_Loc loc)
638#endif // KOLISEO_HAS_LOCATE
639{
640#ifndef KOLISEO_HAS_LOCATE
641 return kls_new_alloc_ext(size, alloc_func, free_func, KLS_DEFAULT_HOOKS, KLS_DEFAULT_EXTENSION_DATA);
642#else
643 return kls_new_alloc_ext_dbg(size, alloc_func, free_func, KLS_DEFAULT_HOOKS, KLS_DEFAULT_EXTENSION_DATA, loc);
644#endif // KOLISEO_HAS_LOCATE
645}
646
659Koliseo *kls_new(ptrdiff_t size)
660{
662}
663
680Koliseo *kls_new_conf_alloc_ext(ptrdiff_t size, KLS_Conf conf, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Hooks ext_handlers, void* user)
681{
682 Koliseo *k = kls_new_alloc_ext(size, alloc_func, free_func, ext_handlers, user);
683 bool conf_res = kls_set_conf(k, conf);
684 if (!conf_res) {
685 fprintf(stderr,
686 "[ERROR] [%s()]: Failed to set config for new Koliseo.\n",
687 __func__);
688 exit(EXIT_FAILURE);
689 }
690 return k;
691}
692
709Koliseo *kls_new_conf_alloc(ptrdiff_t size, KLS_Conf conf, kls_alloc_func alloc_func, kls_free_func free_func)
710{
711 return kls_new_conf_alloc_ext(size, conf, alloc_func, free_func, KLS_DEFAULT_HOOKS, KLS_DEFAULT_EXTENSION_DATA);
712}
713
726Koliseo *kls_new_conf_ext(ptrdiff_t size, KLS_Conf conf, KLS_Hooks ext_handlers, void* user)
727{
728 return kls_new_conf_alloc_ext(size, conf, KLS_DEFAULT_ALLOCF, KLS_DEFAULT_FREEF, ext_handlers, user);
729}
730
742Koliseo *kls_new_conf(ptrdiff_t size, KLS_Conf conf)
743{
745}
746
762Koliseo *kls_new_traced_alloc_handled_ext(ptrdiff_t size, const char *output_path, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers, KLS_Hooks ext_handlers, void* user)
763{
764
765#ifndef KLS_DEBUG_CORE
766 fprintf(stderr,
767 "[WARN] %s(): KLS_DEBUG_CORE is not defined. No tracing allowed.\n",
768 __func__);
769#endif
770 KLS_Conf k = (KLS_Conf) {
771 .collect_stats = 1,.verbose_lvl =
772 1,.log_filepath = output_path,
773#ifndef KOLISEO_HAS_LOCATE
774 .err_handlers.OOM_handler = (err_handlers.OOM_handler != NULL ? err_handlers.OOM_handler : &KLS_OOM_default_handler__),
775 .err_handlers.PTRDIFF_MAX_handler = ( err_handlers.PTRDIFF_MAX_handler != NULL ? err_handlers.PTRDIFF_MAX_handler : &KLS_PTRDIFF_MAX_default_handler__),
776#else
777 .err_handlers.OOM_handler = (err_handlers.OOM_handler != NULL ? err_handlers.OOM_handler : &KLS_OOM_default_handler_dbg__),
778 .err_handlers.PTRDIFF_MAX_handler = ( err_handlers.PTRDIFF_MAX_handler != NULL ? err_handlers.PTRDIFF_MAX_handler : &KLS_PTRDIFF_MAX_default_handler_dbg__),
779#endif // KOLISEO_HAS_LOCATE
780 };
781 return kls_new_conf_alloc_ext(size, k, alloc_func, free_func, ext_handlers, user);
782}
783
798Koliseo *kls_new_traced_alloc_handled(ptrdiff_t size, const char *output_path, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers)
799{
800 return kls_new_traced_alloc_handled_ext(size, output_path, alloc_func, free_func, err_handlers, KLS_DEFAULT_HOOKS, KLS_DEFAULT_EXTENSION_DATA);
801}
802
815Koliseo *kls_new_traced_ext(ptrdiff_t size, const char *output_path, KLS_Hooks ext_handlers, void* user)
816{
818 return kls_new_traced_alloc_handled_ext(size, output_path, KLS_DEFAULT_ALLOCF, KLS_DEFAULT_FREEF, err_handlers, ext_handlers, user);
819}
820
834Koliseo *kls_new_traced_alloc(ptrdiff_t size, const char *output_path, kls_alloc_func alloc_func, kls_free_func free_func)
835{
837 return kls_new_traced_alloc_handled(size, output_path, alloc_func, free_func, err_handlers);
838}
839
851Koliseo *kls_new_traced(ptrdiff_t size, const char *output_path)
852{
854}
855
868Koliseo *kls_new_traced_handled(ptrdiff_t size, const char *output_path, KLS_Err_Handlers err_handlers)
869{
870 return kls_new_traced_alloc_handled(size, output_path, KLS_DEFAULT_ALLOCF, KLS_DEFAULT_FREEF, err_handlers);
871}
872
886Koliseo *kls_new_dbg_alloc_handled_ext(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers, KLS_Hooks ext_handlers, void* user)
887{
888#ifndef KLS_DEBUG_CORE
889 fprintf(stderr,
890 "[WARN] %s(): KLS_DEBUG_CORE is not defined. No debugging support.\n",
891 __func__);
892#endif
893 KLS_Conf k = (KLS_Conf) {
894 .collect_stats = 1,.verbose_lvl = 0,
895#ifndef KOLISEO_HAS_LOCATE
896 .err_handlers.OOM_handler = ( err_handlers.OOM_handler != NULL ? err_handlers.OOM_handler : &KLS_OOM_default_handler__),
897 .err_handlers.PTRDIFF_MAX_handler = ( err_handlers.PTRDIFF_MAX_handler != NULL ? err_handlers.PTRDIFF_MAX_handler : &KLS_PTRDIFF_MAX_default_handler__),
898#else
899 .err_handlers.OOM_handler = ( err_handlers.OOM_handler != NULL ? err_handlers.OOM_handler : &KLS_OOM_default_handler_dbg__),
900 .err_handlers.PTRDIFF_MAX_handler = ( err_handlers.PTRDIFF_MAX_handler != NULL ? err_handlers.PTRDIFF_MAX_handler : &KLS_PTRDIFF_MAX_default_handler_dbg__),
901#endif // KOLIEO_HAS_LOCATE
902 };
903 Koliseo * kls = kls_new_conf_alloc_ext(size, k, alloc_func, free_func, ext_handlers, user);
904 kls->conf.verbose_lvl = 1;
905 return kls;
906}
907
920Koliseo *kls_new_dbg_alloc_handled(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers)
921{
922 return kls_new_dbg_alloc_handled_ext(size, alloc_func, free_func, err_handlers, KLS_DEFAULT_HOOKS, KLS_DEFAULT_EXTENSION_DATA);
923}
924
935Koliseo *kls_new_dbg_ext(ptrdiff_t size, KLS_Hooks ext_handlers, void* user)
936{
938 return kls_new_dbg_alloc_handled_ext(size, KLS_DEFAULT_ALLOCF, KLS_DEFAULT_FREEF, err_handlers, ext_handlers, user);
939}
940
952Koliseo *kls_new_dbg_alloc(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func)
953{
955 return kls_new_dbg_alloc_handled(size, alloc_func, free_func, err_handlers);
956}
957
967Koliseo *kls_new_dbg(ptrdiff_t size)
968{
970}
971
982Koliseo *kls_new_dbg_handled(ptrdiff_t size, KLS_Err_Handlers err_handlers)
983{
985}
986
993bool kls_set_conf(Koliseo *kls, KLS_Conf conf)
994{
995 if (kls == NULL) {
996 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
997 //TODO: is it better to exit() here?
998 return false;
999 }
1000
1001 kls->conf = conf;
1002 if (kls->conf.log_fp == NULL) {
1003 kls->conf.log_fp = stderr;
1004#ifdef KLS_DEBUG_CORE
1005#ifdef KLS_SETCONF_DEBUG
1006 kls_log(kls, "KLS",
1007 "[%s()]: Preliminary set of conf.log_fp to stderr.",
1008 __func__);
1009#endif
1010#endif // KLS_DEBUG_CORE
1011 }
1012
1013 if (conf.err_handlers.OOM_handler == NULL) {
1014 fprintf(stderr,
1015 "[ERROR] at %s(): passed OOM_handler is NULL. Using default.\n",
1016 __func__);
1017#ifdef KLS_DEBUG_CORE
1018#ifdef KLS_SETCONF_DEBUG
1019 kls_log(kls, "KLS",
1020 "[%s()]: Passed OOM_handler was NULL, using default.",
1021 __func__);
1022#endif
1023#endif // KLS_DEBUG_CORE
1024#ifndef KOLISEO_HAS_LOCATE
1026#else
1027 kls->conf.err_handlers.OOM_handler = &KLS_OOM_default_handler_dbg__;
1028#endif
1029 }
1030
1031 if (conf.err_handlers.PTRDIFF_MAX_handler == NULL) {
1032 fprintf(stderr,
1033 "[ERROR] at %s(): passed PTRDIFF_MAX_handler is NULL. Using default.\n",
1034 __func__);
1035#ifdef KLS_DEBUG_CORE
1036#ifdef KLS_SETCONF_DEBUG
1037 kls_log(kls, "KLS",
1038 "[%s()]: Passed PTRDIFF_MAX_handler was NULL, using default.",
1039 __func__);
1040#endif
1041#endif // KLS_DEBUG_CORE
1042#ifndef KOLISEO_HAS_LOCATE
1044#else
1045 kls->conf.err_handlers.PTRDIFF_MAX_handler = &KLS_PTRDIFF_MAX_default_handler_dbg__;
1046#endif
1047 }
1048
1049#ifndef KLS_DEBUG_CORE
1050 if (kls->conf.collect_stats == 1) {
1051 fprintf(stderr,
1052 "[WARN] [%s()]: KLS_DEBUG_CORE is not defined. Stats may not be collected in full.\n",
1053 __func__);
1054 }
1055#endif
1056
1057 if (kls->conf.verbose_lvl > 0) {
1058 if (kls->conf.log_fp != NULL) {
1059#ifdef KLS_DEBUG_CORE
1060#ifdef KLS_SETCONF_DEBUG
1061 kls_log(kls, "WARN",
1062 "[%s()]: kls->conf.log_fp was not NULL. Overriding it.",
1063 __func__);
1064#endif
1065#endif
1066 }
1067
1068 FILE *log_fp = NULL;
1069 log_fp = fopen(kls->conf.log_filepath, "w");
1070 if (!log_fp) {
1071 fprintf(stderr,
1072 "[ERROR] [%s()]: Failed opening logfile at {\"%s\"} [write].\n",
1073 __func__, kls->conf.log_filepath);
1074 return false;
1075 } else {
1076 fprintf(log_fp, "%s", ""); //Reset log_fp
1077 fclose(log_fp);
1078 }
1079 log_fp = fopen(kls->conf.log_filepath, "a");
1080 if (!log_fp) {
1081 fprintf(stderr,
1082 "[ERROR] [%s()]: Failed opening logfile at {\"%s\"} [append].\n",
1083 __func__, kls->conf.log_filepath);
1084 return false;
1085 } else {
1086 kls->conf.log_fp = log_fp;
1087 }
1088 }
1089 return true;
1090}
1091
1092static bool kls__try_grow(Koliseo* kls, ptrdiff_t needed);
1093
1105#ifndef KOLISEO_HAS_LOCATE
1106KLS_Push_Result kls__advance(Koliseo* kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t* padding, const char* caller_name)
1107#else
1108KLS_Push_Result kls__advance_dbg(Koliseo* kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t* padding, const char* caller_name, Koliseo_Loc loc)
1109#endif // KOLISEO_HAS_LOCATE
1110{
1111#ifdef KLS_DEBUG_CORE
1112#ifndef _WIN32
1113 struct timespec start_time, end_time;
1114 clock_gettime(CLOCK_MONOTONIC, &start_time);
1115#else
1116 LARGE_INTEGER start_time, end_time, frequency;
1117 QueryPerformanceFrequency(&frequency);
1118 QueryPerformanceCounter(&start_time);
1119#endif
1120#endif
1121
1122 if (kls == NULL) {
1123 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", caller_name);
1124 exit(EXIT_FAILURE);
1125 }
1126 if ((kls->has_temp == 1) && (kls->conf.block_while_has_temp == 1)) {
1127 return (KLS_Push_Result) {
1128 .p = NULL,
1130 };
1131 }
1132
1133#ifndef KOLISEO_HAS_LOCATE
1134 KLS_Push_Error res = kls__check_available(kls, size, align, count, __func__);
1135#else
1136 KLS_Push_Error res = kls__check_available_dbg(kls, size, align, count, __func__, loc);
1137#endif
1138 if (res != 0) {
1139 return (KLS_Push_Result) {
1140 .p = NULL,
1141 .error = res,
1142 };
1143 }
1144 Koliseo* current = kls;
1145 while (current->next != NULL) {
1146 current = current->next;
1147 }
1148 const ptrdiff_t pad = -current->offset & (align - 1);
1149 *padding = pad;
1150 char *p = current->data + current->offset + pad;
1151 current->prev_offset = current->offset;
1152 current->offset += pad + size * count;
1153
1154 KLS_ASAN_UNPOISON(p, size * count);
1155
1156 char h_size[200];
1157 kls_formatSize(size * count, h_size, sizeof(h_size));
1158 //sprintf(msg,"Pushed zeroes, size (%li) for KLS.",size);
1159 //kls_log("KLS",msg);
1160#ifdef KLS_DEBUG_CORE
1161 kls_log(current, "KLS", "Pushed zeroes on KLS, size (%s). Curr offset: { %p }.", h_size, current->data + current->offset);
1162 if (current->conf.collect_stats == 1) {
1163#ifndef _WIN32
1164 clock_gettime(CLOCK_MONOTONIC, &end_time); // %.9f
1165 double elapsed_time =
1166 (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec -
1167 start_time.tv_nsec) / 1e9;
1168#else
1169 QueryPerformanceCounter(&end_time); // %.7f
1170 double elapsed_time =
1171 (double)(end_time.QuadPart -
1172 start_time.QuadPart) / frequency.QuadPart;
1173#endif
1174 if (elapsed_time > current->stats.worst_pushcall_time) {
1175 current->stats.worst_pushcall_time = elapsed_time;
1176 }
1177 }
1178#endif
1179 if (current->conf.collect_stats == 1) {
1180 current->stats.tot_pushes += 1;
1181 }
1182 return (KLS_Push_Result) {
1183 .p = p,
1184 .error = KLS_PUSH_OK,
1185 };
1186}
1187
1200#ifndef KOLISEO_HAS_LOCATE
1201KLS_Push_Error kls__check_available(Koliseo* kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, const char* caller_name)
1202#else
1203KLS_Push_Error kls__check_available_dbg(Koliseo* kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, const char* caller_name, Koliseo_Loc loc)
1204#endif // KOLISEO_HAS_LOCATE
1205{
1206 assert(kls != NULL);
1207 assert(caller_name != NULL);
1208 if (count < 0) {
1210 }
1211 if (size < 1) {
1212 return KLS_PUSH_SIZE_LT1;
1213 }
1214 if (align < 1) {
1215 return KLS_PUSH_ALIGN_LT1;
1216 }
1217 if (! ((align & (align - 1)) == 0)) {
1219 }
1220 Koliseo* current = kls;
1221 while (current->next != NULL) {
1222 current = current->next;
1223 }
1224 const ptrdiff_t available = current->size - current->offset;
1225 const ptrdiff_t padding = -current->offset & (align - 1);
1226 if (count == 0) {
1227 if (current->conf.allow_zerocount_push != 1) {
1228 return KLS_PUSH_ZEROCOUNT;
1229 } else {
1230#ifdef KLS_DEBUG_CORE
1231 kls_log(current, "DEBUG", "Accepting zero-count push: conf.allow_zerocount_push was 1");
1232#endif // KLS_DEBUG_CORE
1233 }
1234 }
1235
1236 if (count > PTRDIFF_MAX / size || available - padding < size * count) {
1237 if (count > PTRDIFF_MAX / size) {
1238 return KLS_PUSH_PTRDIFF_MAX;
1239 } else {
1240 if (current->conf.growable == 1 && kls__try_grow(current, (size * count) + padding)) {
1241 return KLS_PUSH_OK;
1242 }
1243 return KLS_PUSH_OOM;
1244 }
1245 }
1246 return KLS_PUSH_OK;
1247}
1248
1260#ifndef KOLISEO_HAS_LOCATE
1261KLS_Push_Result kls__temp_advance(Koliseo_Temp* kls_t, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t* padding, const char* caller_name)
1262#else
1263KLS_Push_Result kls__temp_advance_dbg(Koliseo_Temp* kls_t, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t* padding, const char* caller_name, Koliseo_Loc loc)
1264#endif // KOLISEO_HAS_LOCATE
1265{
1266#ifdef KLS_DEBUG_CORE
1267#ifndef _WIN32
1268 struct timespec start_time, end_time;
1269 clock_gettime(CLOCK_MONOTONIC, &start_time);
1270#else
1271 LARGE_INTEGER start_time, end_time, frequency;
1272 QueryPerformanceFrequency(&frequency);
1273 QueryPerformanceCounter(&start_time);
1274#endif
1275#endif
1276
1277 if (kls_t == NULL) {
1278 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo_Temp was NULL.\n",
1279 __func__);
1280 exit(EXIT_FAILURE);
1281 }
1282 Koliseo *kls = kls_t->kls;
1283 if (kls == NULL) {
1284 fprintf(stderr, "[ERROR] [%s()]: Referred Koliseo was NULL.\n",
1285 __func__);
1286 exit(EXIT_FAILURE);
1287 }
1288#ifndef KOLISEO_HAS_LOCATE
1289 KLS_Push_Error res = kls__check_available(kls, size, align, count, __func__);
1290#else
1291 KLS_Push_Error res = kls__check_available_dbg(kls, size, align, count, __func__, loc);
1292#endif
1293 if (res != 0) {
1294 return (KLS_Push_Result) {
1295 .p = NULL,
1296 .error = res,
1297 };
1298 }
1299 Koliseo* current = kls;
1300 while (current->next != NULL) {
1301 current = current->next;
1302 }
1303 ptrdiff_t pad = -current->offset & (align - 1);
1304 char *p = current->data + current->offset + pad;
1305 *padding = pad;
1306 current->prev_offset = current->offset;
1307 current->offset += pad + size * count;
1308
1309 KLS_ASAN_UNPOISON(p, size * count);
1310
1311 char h_size[200];
1312 kls_formatSize(size * count, h_size, sizeof(h_size));
1313 //sprintf(msg,"Pushed zeroes, size (%li) for KLS.",size);
1314 //kls_log("KLS",msg);
1315#ifdef KLS_DEBUG_CORE
1316 if (current->conf.collect_stats == 1) {
1317#ifndef _WIN32
1318 clock_gettime(CLOCK_MONOTONIC, &end_time); // %.9f
1319 double elapsed_time =
1320 (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec -
1321 start_time.tv_nsec) / 1e9;
1322#else
1323 QueryPerformanceCounter(&end_time); // %.7f
1324 double elapsed_time =
1325 (double)(end_time.QuadPart -
1326 start_time.QuadPart) / frequency.QuadPart;
1327#endif
1328 if (elapsed_time > current->stats.worst_pushcall_time) {
1329 current->stats.worst_pushcall_time = elapsed_time;
1330 }
1331 }
1332 kls_log(current, "KLS", "Pushed zeroes on Temp_KLS, size (%s). Curr offset: { %p }.", h_size, current->data + current->offset);
1333#endif
1334 if (current->conf.collect_stats == 1) {
1335 current->stats.tot_temp_pushes += 1;
1336 }
1337 return (KLS_Push_Result) {
1338 .p = p,
1339 .error = KLS_PUSH_OK,
1340 };
1341}
1342
1343bool kls__try_grow(Koliseo* kls, ptrdiff_t needed)
1344{
1345 assert(kls->next == NULL);
1346 ptrdiff_t new_size = KLS_MAX(kls->size * 2, needed);
1347 KLS_Hooks hooks = kls->hooks;
1348 hooks.on_new_handler = NULL; // We don't want the extension handler to run again on the tail
1349 // since the extension_data is shared
1351 kls_log(kls, "DEBUG", "%s(): growing Koliseo, new size: {%td}", __func__, new_size);
1352 if (!new_kls) return false;
1353 kls->next = new_kls;
1354 return true;
1355}
1356
1367void *kls_push(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
1368{
1369 ptrdiff_t padding = 0;
1370#ifndef KOLISEO_HAS_LOCATE
1371 KLS_Push_Result res = kls__advance(kls, size, align, count, &padding, __func__);
1372 return kls__handle_push_result(kls, res, size, align, count, padding, __func__);
1373#else
1374 KLS_Push_Result res = kls__advance_dbg(kls, size, align, count, &padding, __func__, KLS_HERE);
1375 return kls__handle_push_result_dbg(kls, res, size, align, count, padding, __func__, KLS_HERE);
1376#endif // KOLISEO_HAS_LOCATE
1377}
1378
1389#ifndef KOLISEO_HAS_LOCATE
1390void *kls_push_zero(Koliseo *kls, ptrdiff_t size, ptrdiff_t align,
1391 ptrdiff_t count)
1392#else
1393void *kls_push_zero_dbg(Koliseo *kls, ptrdiff_t size, ptrdiff_t align,
1394 ptrdiff_t count, Koliseo_Loc loc)
1395#endif // KOLISEO_HAS_LOCATE
1396{
1397 ptrdiff_t padding = 0;
1398#ifndef KOLISEO_HAS_LOCATE
1399 KLS_Push_Result res = kls__advance(kls, size, align, count, &padding, __func__);
1400 void* p = kls__handle_push_result(kls, res, size, align, count, padding, __func__);
1401#else
1402 KLS_Push_Result res = kls__advance_dbg(kls, size, align, count, &padding, __func__, loc);
1403 void* p = kls__handle_push_result_dbg(kls, res, size, align, count, padding, __func__, loc);
1404#endif // KOLISEO_HAS_LOCATE
1405 if (!p) return NULL;
1406 //Zero new area
1407 memset(p, 0, size * count);
1408 return p;
1409}
1410
1422#ifndef KOLISEO_HAS_LOCATE
1423void *kls_push_zero_ext(Koliseo *kls, ptrdiff_t size, ptrdiff_t align,
1424 ptrdiff_t count)
1425#else
1426void *kls_push_zero_ext_dbg(Koliseo *kls, ptrdiff_t size, ptrdiff_t align,
1427 ptrdiff_t count, Koliseo_Loc loc)
1428#endif // KOLISEO_HAS_LOCATE
1429{
1430
1431 ptrdiff_t padding = 0;
1432#ifndef KOLISEO_HAS_LOCATE
1433 KLS_Push_Result res = kls__advance(kls, size, align, count, &padding, __func__);
1434 void* p = kls__handle_push_result(kls, res, size, align, count, padding, __func__);
1435#else
1436 KLS_Push_Result res = kls__advance_dbg(kls, size, align, count, &padding, __func__, loc);
1437 void* p = kls__handle_push_result_dbg(kls, res, size, align, count, padding, __func__, loc);
1438#endif // KOLISEO_HAS_LOCATE
1439 if (!p) return NULL;
1440 //Zero new area
1441 memset(p, 0, size * count);
1442
1443 Koliseo* current = kls;
1444 while (current->next != NULL) {
1445 current = current->next;
1446 }
1447
1448 if (current->hooks.on_push_handler != NULL) {
1449 /*
1450 struct KLS_EXTENSION_AR_DEFAULT_ARGS {
1451 const char* region_name;
1452 size_t region_name_len;
1453 const char* region_desc;
1454 size_t region_desc_len;
1455 int region_type;
1456 };
1457 struct KLS_EXTENSION_AR_DEFAULT_ARGS ar_args = {
1458 .region_name = KOLISEO_DEFAULT_REGION_NAME,
1459 .region_name_len = strlen(KOLISEO_DEFAULT_REGION_NAME),
1460 .region_desc = KOLISEO_DEFAULT_REGION_DESC,
1461 .region_desc_len = strlen(KOLISEO_DEFAULT_REGION_DESC),
1462 .region_type = KLS_None
1463 };
1464 kls->hooks.on_push_handler(kls, padding, (void*)&ar_args);
1465 */
1466 current->hooks.on_push_handler(current, padding, __func__, NULL);
1467 }
1468 return p;
1469}
1470
1471#ifndef KOLISEO_HAS_LOCATE
1472char* kls_vsprintf(Koliseo* kls, const char* fmt, va_list args)
1473#else
1474char* kls_vsprintf_dbg(Koliseo* kls, Koliseo_Loc loc, const char* fmt, va_list args)
1475#endif // KOLISEO_HAS_LOCATE
1476{
1477 va_list args_copy;
1478 va_copy(args_copy, args);
1479 int len = vsnprintf(NULL, 0, fmt, args);
1480#ifndef KOLISEO_HAS_LOCATE
1481 char* str = KLS_PUSH_ARR(kls, char, len+1);
1482#else
1483 char* str = kls_push_zero_ext_dbg(kls, sizeof(char), KLS_ALIGNOF(char), len+1, loc);
1484#endif // KOLISEO_HAS_LOCATE
1485 vsnprintf(str, len+1, fmt, args_copy);
1486 va_end(args_copy);
1487 return str;
1488}
1489
1496#ifndef KOLISEO_HAS_LOCATE
1497char* kls_sprintf(Koliseo* kls, const char* fmt, ...)
1498#else
1499char* kls_sprintf_dbg(Koliseo* kls, Koliseo_Loc loc, const char* fmt, ...)
1500#endif // KOLISEO_HAS_LOCATE
1501{
1502 va_list args;
1503 va_start(args, fmt);
1504#ifndef KOLISEO_HAS_LOCATE
1505 char* str = kls_vsprintf(kls, fmt, args);
1506#else
1507 char* str = kls_vsprintf_dbg(kls, loc, fmt, args);
1508#endif // KOLISEO_HAS_LOCATE
1509 va_end(args);
1510 return str;
1511}
1512
1524#ifndef KOLISEO_HAS_LOCATE
1525void *kls_temp_push_zero_ext(Koliseo_Temp *t_kls, ptrdiff_t size,
1526 ptrdiff_t align, ptrdiff_t count)
1527#else
1528void *kls_temp_push_zero_ext_dbg(Koliseo_Temp *t_kls, ptrdiff_t size,
1529 ptrdiff_t align, ptrdiff_t count, Koliseo_Loc loc)
1530#endif // KOLISEO_HAS_LOCATE
1531{
1532
1533 ptrdiff_t padding = 0;
1534
1535#ifndef KOLISEO_HAS_LOCATE
1536 KLS_Push_Result res = kls__temp_advance(t_kls, size, align, count, &padding, __func__);
1537#else
1538 KLS_Push_Result res = kls__temp_advance_dbg(t_kls, size, align, count, &padding, __func__, loc);
1539#endif // KOLISEO_HAS_LOCATE
1540 if (res.error) return NULL;
1541 //Zero new area
1542 memset(res.p, 0, size * count);
1543
1544 Koliseo* kls = t_kls->kls;
1545 Koliseo* current = kls;
1546 while (current->next != NULL) {
1547 current = current->next;
1548 }
1549
1550 if (current->hooks.on_temp_push_handler != NULL) {
1551 // Call on_temp_push extension with empty user arg
1552 current->hooks.on_temp_push_handler(t_kls, padding, __func__, NULL);
1553 }
1554 return res.p;
1555}
1556
1557#ifndef KOLISEO_HAS_LOCATE
1558char* kls_temp_vsprintf(Koliseo_Temp* kls_t, const char* fmt, va_list args)
1559#else
1560char* kls_temp_vsprintf_dbg(Koliseo_Temp* kls_t, Koliseo_Loc loc, const char* fmt, va_list args)
1561#endif // KOLISEO_HAS_LOCATE
1562{
1563 va_list args_copy;
1564 va_copy(args_copy, args);
1565 int len = vsnprintf(NULL, 0, fmt, args);
1566#ifndef KOLISEO_HAS_LOCATE
1567 char* str = KLS_PUSH_ARR_T(kls_t, char, len+1);
1568#else
1569 char* str = kls_temp_push_zero_ext_dbg(kls_t, sizeof(char), KLS_ALIGNOF(char), len+1, loc);
1570#endif // KOLISEO_HAS_LOCATE
1571 vsnprintf(str, len+1, fmt, args_copy);
1572 va_end(args_copy);
1573 return str;
1574}
1575
1576
1583#ifndef KOLISEO_HAS_LOCATE
1584char* kls_temp_sprintf(Koliseo_Temp* kls_t, const char* fmt, ...)
1585#else
1586char* kls_temp_sprintf_dbg(Koliseo_Temp* kls_t, Koliseo_Loc loc, const char* fmt, ...)
1587#endif // KOLISEO_HAS_LOCATE
1588{
1589 va_list args;
1590 va_start(args, fmt);
1591#ifndef KOLISEO_HAS_LOCATE
1592 char* str = kls_temp_vsprintf(kls_t, fmt, args);
1593#else
1594 char* str = kls_temp_vsprintf_dbg(kls_t, loc, fmt, args);
1595#endif // KOLISEO_HAS_LOCATE
1596 va_end(args);
1597 return str;
1598}
1599
1605bool kls_contains_pointer(const Koliseo *kls, const void *ptr)
1606{
1607 const char *p = ptr;
1608
1609 for (const Koliseo *cur = kls; cur; cur = cur->next) {
1610 if (p >= cur->data &&
1611 p < cur->data + cur->offset) {
1612 return true;
1613 }
1614 }
1615
1616 return false;
1617}
1618
1630#ifndef KOLISEO_HAS_LOCATE
1631void *kls_repush(Koliseo *kls, void* old, ptrdiff_t size, ptrdiff_t align,
1632 ptrdiff_t old_count, ptrdiff_t new_count)
1633#else
1634void *kls_repush_dbg(Koliseo *kls, void* old, ptrdiff_t size, ptrdiff_t align,
1635 ptrdiff_t old_count, ptrdiff_t new_count, Koliseo_Loc loc)
1636#endif // KOLISEO_HAS_LOCATE
1637{
1638 if (!old) {
1639#ifndef KOLISEO_HAS_LOCATE
1640 fprintf(stderr,
1641 "[KLS] %s(): old was NULL.\n",
1642 __func__);
1643#else
1644 fprintf(stderr,
1645 "[KLS] " KLS_Loc_Fmt "%s(): old was NULL.\n",
1646 KLS_Loc_Arg(loc),
1647 __func__);
1648#endif // KOLISEO_HAS_LOCATE
1649 return NULL;
1650 }
1651 if (!kls_contains_pointer(kls, old)) {
1652 fprintf(stderr,
1653 "[KLS] %s(): pointer %p does not belong to this Koliseo.\n",
1654 __func__,
1655 old);
1656 return NULL;
1657 }
1658 if (old_count < 0) {
1659#ifndef KOLISEO_HAS_LOCATE
1660 fprintf(stderr,
1661 "[KLS] %s(): old_count [%td] was < 0.\n",
1662 __func__,
1663 old_count);
1664#else
1665 fprintf(stderr,
1666 "[KLS] " KLS_Loc_Fmt "%s(): old_count [%td] was < 0.\n",
1667 KLS_Loc_Arg(loc),
1668 __func__,
1669 old_count);
1670#endif // KOLISEO_HAS_LOCATE
1671 return NULL;
1672 }
1673 if (new_count < 0) {
1674#ifndef KOLISEO_HAS_LOCATE
1675 fprintf(stderr,
1676 "[KLS] %s(): new_count [%td] was < 0.\n",
1677 __func__,
1678 new_count);
1679#else
1680 fprintf(stderr,
1681 "[KLS] " KLS_Loc_Fmt "%s(): new_count [%td] was < 0.\n",
1682 KLS_Loc_Arg(loc),
1683 __func__,
1684 new_count);
1685#endif // KOLISEO_HAS_LOCATE
1686 return NULL;
1687 }
1688 if (size < 1) {
1689#ifndef KOLISEO_HAS_LOCATE
1690 fprintf(stderr,
1691 "[KLS] %s(): size [%td] was < 1.\n",
1692 __func__,
1693 size);
1694#else
1695 fprintf(stderr,
1696 "[KLS] " KLS_Loc_Fmt "%s(): size [%td] was < 1.\n",
1697 KLS_Loc_Arg(loc),
1698 __func__,
1699 size);
1700#endif // KOLISEO_HAS_LOCATE
1701 return NULL;
1702 }
1703 if (align < 1) {
1704#ifndef KOLISEO_HAS_LOCATE
1705 fprintf(stderr,
1706 "[KLS] %s(): align [%td] was < 1.\n",
1707 __func__,
1708 align);
1709#else
1710 fprintf(stderr,
1711 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was < 1.\n",
1712 KLS_Loc_Arg(loc),
1713 __func__,
1714 align);
1715#endif // KOLISEO_HAS_LOCATE
1716 return NULL;
1717 }
1718 if (! ((align & (align - 1)) == 0)) {
1719#ifndef KOLISEO_HAS_LOCATE
1720 fprintf(stderr,
1721 "[KLS] %s(): align [%td] was not a power of 2.\n",
1722 __func__,
1723 align);
1724#else
1725 fprintf(stderr,
1726 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was not a power of 2.\n",
1727 KLS_Loc_Arg(loc),
1728 __func__,
1729 align);
1730#endif // KOLISEO_HAS_LOCATE
1731 return NULL;
1732 }
1733 if (kls->has_temp == 1 && kls->conf.block_while_has_temp == 1) {
1734 fprintf(stderr, "%s(): kls has an active temp\n", __func__);
1735 return NULL;
1736 }
1737 if (old_count >= new_count) return old;
1738
1739 ptrdiff_t growth = new_count - old_count;
1740
1741 if ((size_t)old_count > SIZE_MAX / (size_t)size) return NULL;
1742
1743 if ((size_t)new_count > SIZE_MAX / (size_t)size) return NULL;
1744
1745 size_t old_size = (size_t)old_count * (size_t)size;
1746 size_t new_size = (size_t)new_count * (size_t)size;
1747
1748 Koliseo* current = kls;
1749 while (current->next != NULL) {
1750 current = current->next;
1751 }
1752
1753 ptrdiff_t padding = 0;
1754 bool is_last_alloc = old == (current->data + current->prev_offset);
1755
1756 void* new_ptr = NULL;
1757 if (is_last_alloc) {
1758 // Extend last allocation
1759
1760 // Save prev_offset
1761 const ptrdiff_t saved_prev_offset = current->prev_offset;
1762#ifndef KOLISEO_HAS_LOCATE
1763 KLS_Push_Result res = kls__advance(current, size, align, growth, &padding, __func__);
1764 void* p = kls__handle_push_result(current, res, size, align, growth, padding, __func__);
1765#else
1766 KLS_Push_Result res = kls__advance_dbg(current, size, align, growth, &padding, __func__, loc);
1767 void* p = kls__handle_push_result_dbg(current, res, size, align, growth, padding, __func__, loc);
1768#endif // KOLISEO_HAS_LOCATE
1769 if (!p) return NULL;
1770 size_t added_size = new_size - old_size;
1771 //Zero new area
1772 memset(p, 0, added_size);
1773 new_ptr = old;
1774
1775 Koliseo* new_current = current;
1776 while (new_current->next != NULL) {
1777 new_current = new_current->next;
1778 }
1779
1780#ifdef KLS_DEBUG_CORE
1781 const ptrdiff_t new_byte_slice_len = new_current->offset - new_current->prev_offset + padding;
1782 kls_log(new_current, "KLS", "Extended last allocation on KLS, new_byte_slice_len (%td), padding (%td). Curr offset: { %p } Old: { %p }, New: { %p }.", new_byte_slice_len, padding, new_current->data + new_current->offset, old, new_ptr);
1783#endif
1784
1785 // Restore saved prev_offset
1786 current->prev_offset = saved_prev_offset;
1787 if (current->hooks.on_repush_last_handler != NULL) {
1788 current->hooks.on_repush_last_handler(current, padding, __func__, NULL);
1789 }
1790 } else {
1791#ifdef KLS_DEBUG_CORE
1792 kls_log(current, "KLS", "%s(): pushed new memory", __func__);
1793#endif
1794 new_ptr = kls_push_zero_ext(kls, size, align, new_count);
1795 if (new_ptr && old_size > 0) {
1796 memcpy(new_ptr, old, old_size);
1797 }
1798 }
1799 return new_ptr;
1800}
1801
1813#ifndef KOLISEO_HAS_LOCATE
1814void *kls_temp_repush(Koliseo_Temp *t_kls, void* old, ptrdiff_t size, ptrdiff_t align,
1815 ptrdiff_t old_count, ptrdiff_t new_count)
1816#else
1817void *kls_temp_repush_dbg(Koliseo_Temp *t_kls, void* old, ptrdiff_t size, ptrdiff_t align,
1818 ptrdiff_t old_count, ptrdiff_t new_count, Koliseo_Loc loc)
1819#endif // KOLISEO_HAS_LOCATE
1820{
1821 if (!old) {
1822#ifndef KOLISEO_HAS_LOCATE
1823 fprintf(stderr,
1824 "[KLS] %s(): old was NULL.\n",
1825 __func__);
1826#else
1827 fprintf(stderr,
1828 "[KLS] " KLS_Loc_Fmt "%s(): old was NULL.\n",
1829 KLS_Loc_Arg(loc),
1830 __func__);
1831#endif // KOLISEO_HAS_LOCATE
1832 return NULL;
1833 }
1834 if (!kls_contains_pointer(t_kls->kls, old)) {
1835 fprintf(stderr,
1836 "[KLS] %s(): pointer %p does not belong to this Koliseo.\n",
1837 __func__,
1838 old);
1839 return NULL;
1840 }
1841 if (old_count < 0) {
1842#ifndef KOLISEO_HAS_LOCATE
1843 fprintf(stderr,
1844 "[KLS] %s(): old_count [%td] was < 0.\n",
1845 __func__,
1846 old_count);
1847#else
1848 fprintf(stderr,
1849 "[KLS] " KLS_Loc_Fmt "%s(): old_count [%td] was < 0.\n",
1850 KLS_Loc_Arg(loc),
1851 __func__,
1852 old_count);
1853#endif // KOLISEO_HAS_LOCATE
1854 return NULL;
1855 }
1856 if (new_count < 0) {
1857#ifndef KOLISEO_HAS_LOCATE
1858 fprintf(stderr,
1859 "[KLS] %s(): new_count [%td] was < 0.\n",
1860 __func__,
1861 new_count);
1862#else
1863 fprintf(stderr,
1864 "[KLS] " KLS_Loc_Fmt "%s(): new_count [%td] was < 0.\n",
1865 KLS_Loc_Arg(loc),
1866 __func__,
1867 new_count);
1868#endif // KOLISEO_HAS_LOCATE
1869 return NULL;
1870 }
1871 if (size < 1) {
1872#ifndef KOLISEO_HAS_LOCATE
1873 fprintf(stderr,
1874 "[KLS] %s(): size [%td] was < 1.\n",
1875 __func__,
1876 size);
1877#else
1878 fprintf(stderr,
1879 "[KLS] " KLS_Loc_Fmt "%s(): size [%td] was < 1.\n",
1880 KLS_Loc_Arg(loc),
1881 __func__,
1882 size);
1883#endif // KOLISEO_HAS_LOCATE
1884 return NULL;
1885 }
1886 if (align < 1) {
1887#ifndef KOLISEO_HAS_LOCATE
1888 fprintf(stderr,
1889 "[KLS] %s(): align [%td] was < 1.\n",
1890 __func__,
1891 align);
1892#else
1893 fprintf(stderr,
1894 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was < 1.\n",
1895 KLS_Loc_Arg(loc),
1896 __func__,
1897 align);
1898#endif // KOLISEO_HAS_LOCATE
1899 return NULL;
1900 }
1901 if (! ((align & (align - 1)) == 0)) {
1902#ifndef KOLISEO_HAS_LOCATE
1903 fprintf(stderr,
1904 "[KLS] %s(): align [%td] was not a power of 2.\n",
1905 __func__,
1906 align);
1907#else
1908 fprintf(stderr,
1909 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was not a power of 2.\n",
1910 KLS_Loc_Arg(loc),
1911 __func__,
1912 align);
1913#endif // KOLISEO_HAS_LOCATE
1914 return NULL;
1915 }
1916
1917 if (old_count >= new_count) return old;
1918
1919 ptrdiff_t growth = new_count - old_count;
1920
1921 if ((size_t)old_count > SIZE_MAX / (size_t)size) return NULL;
1922
1923 if ((size_t)new_count > SIZE_MAX / (size_t)size) return NULL;
1924
1925 size_t old_size = (size_t)old_count * (size_t)size;
1926 size_t new_size = (size_t)new_count * (size_t)size;
1927
1928 Koliseo* current = t_kls->kls;
1929 while (current->next != NULL) {
1930 current = current->next;
1931 }
1932
1933 ptrdiff_t padding = 0;
1934 bool is_last_alloc = old == (current->data + current->prev_offset);
1935
1936 void* new_ptr = NULL;
1937 if (is_last_alloc) {
1938 // Extend last allocation
1939
1940 // Save prev_offset
1941 const ptrdiff_t saved_prev_offset = current->prev_offset;
1942#ifndef KOLISEO_HAS_LOCATE
1943 KLS_Push_Result res = kls__temp_advance(t_kls, size, align, growth, &padding, __func__);
1944 void* p = kls__handle_push_result(current, res, size, align, growth, padding, __func__);
1945#else
1946 KLS_Push_Result res = kls__temp_advance_dbg(t_kls, size, align, growth, &padding, __func__, loc);
1947 void* p = kls__handle_push_result_dbg(current, res, size, align, growth, padding, __func__, loc);
1948#endif // KOLISEO_HAS_LOCATE
1949 if (!p) return NULL;
1950 size_t added_size = new_size - old_size;
1951 //Zero new area
1952 memset(p, 0, added_size);
1953 new_ptr = old;
1954
1955 Koliseo* new_current = current;
1956 while (new_current->next != NULL) {
1957 new_current = new_current->next;
1958 }
1959
1960#ifdef KLS_DEBUG_CORE
1961 const ptrdiff_t new_byte_slice_len = new_current->offset - new_current->prev_offset + padding;
1962 kls_log(new_current, "KLS", "Extended last allocation on Temp_KLS, new_byte_slice_len (%td), padding (%td). Curr offset: { %p } Old: { %p }, New: { %p }.", new_byte_slice_len, padding, new_current->data + new_current->offset, old, new_ptr);
1963#endif
1964
1965 // Restore saved prev_offset
1966 current->prev_offset = saved_prev_offset;
1967 if (current->hooks.on_temp_repush_last_handler != NULL) {
1968 current->hooks.on_temp_repush_last_handler(t_kls, padding, __func__, NULL);
1969 }
1970 } else {
1971#ifdef KLS_DEBUG_CORE
1972 kls_log(current, "KLS", "%s(): pushed new memory", __func__);
1973#endif
1974 new_ptr = kls_temp_push_zero_ext(t_kls, size, align, new_count);
1975 if (new_ptr && old_size > 0) {
1976 memcpy(new_ptr, old, old_size);
1977 }
1978 }
1979 return new_ptr;
1980}
1981
1987void print_kls_2file(FILE *fp, const Koliseo *kls)
1988{
1989 if (fp == NULL) {
1990 fprintf(stderr, "print_kls_2file(): fp was NULL.\n");
1991 return;
1992 }
1993 if (kls == NULL) {
1994 fprintf(fp, "[KLS] kls was NULL.\n");
1995 } else {
1996 fprintf(fp, "\n[KLS] API Level: { %i }\n", int_koliseo_version());
1997 fprintf(fp, "\n[INFO] Conf: { " KLS_Conf_Fmt " }\n",
1998 KLS_Conf_Arg(kls->conf));
1999 fprintf(fp, "\n[INFO] Stats: { " KLS_Stats_Fmt " }\n",
2000 KLS_Stats_Arg(kls->stats));
2001 fprintf(fp, "\n[KLS] Size: { %td }\n", kls->size);
2002 char human_size[200];
2003 char curr_size[200];
2004 kls_formatSize(kls->size, human_size, sizeof(human_size));
2005 fprintf(fp, "[KLS] Size (Human): { %s }\n", human_size);
2006 kls_formatSize(kls->offset, curr_size, sizeof(curr_size));
2007 fprintf(fp, "[KLS] Used (Human): { %s }\n", curr_size);
2008 fprintf(fp, "[KLS] Offset: { %td }\n", kls->offset);
2009 fprintf(fp, "[KLS] Prev_Offset: { %td }\n", kls->prev_offset);
2010 fprintf(fp, "\n");
2011 }
2012}
2013
2018void print_dbg_kls(const Koliseo *kls)
2019{
2020 if (kls == NULL) {
2021 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2022 exit(EXIT_FAILURE);
2023 }
2024 print_kls_2file(stderr, kls);
2025}
2026
2032void print_temp_kls_2file(FILE *fp, const Koliseo_Temp *t_kls)
2033{
2034 if (fp == NULL) {
2035 fprintf(stderr, "print_temp_kls_2file(): fp was NULL.\n");
2036 exit(EXIT_FAILURE);
2037 }
2038 if (t_kls == NULL) {
2039 fprintf(fp, "[KLS_T] t_kls was NULL.");
2040 } else if (t_kls->kls == NULL) {
2041 fprintf(fp, "[KLS_T] [%s()]: Referred Koliseo was NULL.\n", __func__);
2042 } else {
2043 const Koliseo *kls = t_kls->kls;
2044 fprintf(fp, "\n[KLS_T] API Level: { %i }\n", int_koliseo_version());
2045 fprintf(fp, "\n[KLS_T] Temp Size: { %td }\n",
2046 kls->size - t_kls->offset);
2047 fprintf(fp, "\n[KLS_T] Refer Size: { %td }\n", kls->size);
2048 char human_size[200];
2049 char curr_size[200];
2050 kls_formatSize(kls->size - t_kls->offset, human_size,
2051 sizeof(human_size));
2052 fprintf(fp, "[KLS_T] Temp Size Human: { %s }\n", human_size);
2053 kls_formatSize(kls->size, human_size, sizeof(human_size));
2054 fprintf(fp, "[KLS_T] Refer Size Human: { %s }\n", human_size);
2055 kls_formatSize(kls->offset, curr_size, sizeof(curr_size));
2056 fprintf(fp, "[KLS_T] Inner Used (Human): { %s }\n", curr_size);
2057 kls_formatSize(t_kls->offset, curr_size, sizeof(curr_size));
2058 fprintf(fp, "[KLS_T] Temp Used (Human): { %s }\n", curr_size);
2059 fprintf(fp, "[KLS_T] Inner Offset: { %td }\n", kls->offset);
2060 fprintf(fp, "[KLS_T] Temp Offset: { %td }\n", t_kls->offset);
2061 fprintf(fp, "[KLS_T] Inner Prev_Offset: { %td }\n", kls->prev_offset);
2062 fprintf(fp, "[KLS_T] Temp Prev_Offset: { %td }\n\n",
2063 t_kls->prev_offset);
2064 }
2065}
2066
2072{
2073 print_temp_kls_2file(stderr, t_kls);
2074}
2075
2083void kls_formatSize(size_t size, char *outputBuffer, size_t bufferSize)
2084{
2085 static const char *units[] = {
2086 "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
2087 };
2088
2089 const int numUnits = sizeof(units) / sizeof(units[0]);
2090
2091 size_t unitIndex = 0;
2092 long double sizeValue = (long double)size;
2093
2094 while (sizeValue >= 1000 && unitIndex < numUnits - 1) {
2095 sizeValue /= 1000;
2096 unitIndex++;
2097 }
2098
2099 snprintf(outputBuffer, bufferSize, "%.2Lf %s", sizeValue, units[unitIndex]);
2100}
2101
2108{
2109 if (kls == NULL) {
2110 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2111 exit(EXIT_FAILURE);
2112 }
2113 //Reset pointer
2114 kls->prev_offset = kls->offset;
2115 kls->offset = sizeof(*kls);
2116 if (kls->next) {
2117 Koliseo *chain = kls->next;
2118 kls->next = NULL;
2119 if (chain) {
2120 kls_free(chain);
2121 kls->extension_data = NULL; // The chain shares this pointer and we need to restore the extension data
2122 if (kls->hooks.on_new_handler) {
2123 kls->hooks.on_new_handler(kls);
2124 }
2125 }
2126 }
2127 KLS_ASAN_POISON(kls->data + kls->offset, kls->size - kls->offset);
2128#ifdef KLS_DEBUG_CORE
2129 kls_log(kls, "KLS", "API Level { %i } -> Cleared offsets for KLS.",
2131#endif
2132}
2133
2140{
2141 if (kls == NULL) {
2142 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2143 exit(EXIT_FAILURE);
2144 }
2145 Koliseo* current = kls;
2146 while (current) {
2147 if (current->has_temp == 1) {
2148#ifdef KLS_DEBUG_CORE
2149 kls_log(current, "KLS",
2150 "API Level { %i } -> KLS had an active Koliseo_Temp.",
2152#endif
2153 kls_temp_end(current->t_kls);
2154 }
2155 if (current->hooks.on_free_handler != NULL) {
2156 // Call on_free() extension
2157 current->hooks.on_free_handler(current);
2158 for (Koliseo *k = current; k; k = k->next) {
2159 // We NULL all subsequent extension_data pointers, since the chain shares it
2160 // and it's freed in the first hook call
2161 k->extension_data = NULL;
2162 }
2163 }
2164 Koliseo* next = current->next;
2165 current->next = NULL;
2166 //kls_clear(current);
2167#ifdef KLS_DEBUG_CORE
2168 kls_log(current, "KLS", "API Level { %i } -> Freeing KLS.",
2170#endif
2171 if (current->conf.log_fp != NULL && current->conf.log_fp != stdout
2172 && current->conf.log_fp != stderr) {
2173#ifdef KLS_DEBUG_CORE
2174 kls_log(current, "KLS", "Closing kls log file. Path: {\"%s\"}.",
2175 kls->conf.log_filepath);
2176#endif
2177 int close_res = fclose(current->conf.log_fp);
2178 if (close_res != 0) {
2179 fprintf(stderr,
2180 "[ERROR] %s(): Failed fclose() on log_fp. Path: {\"%s\"}.",
2181 __func__, current->conf.log_filepath);
2182 }
2183 } else if (current->conf.log_fp == stdout || current->conf.log_fp == stderr) {
2184 if (current->conf.verbose_lvl > 1) {
2185 fprintf(stderr,
2186 "[INFO] %s(): kls->conf.log_fp is %s. Not closing it.\n",
2187 __func__,
2188 (current->conf.log_fp == stdout ? "stdout" : "stderr"));
2189 }
2190 }
2191 if (current->free_func == NULL) {
2192 fprintf(stderr,
2193 "[ERROR] %s(): free function was NULL.\n", __func__);
2194 return;
2195 }
2196 current->free_func(current);
2197 current = next;
2198 }
2199}
2200
2208#ifndef KOLISEO_HAS_LOCATE
2210#else
2211Koliseo_Temp *kls_temp_start_dbg(Koliseo *kls, Koliseo_Loc loc)
2212#endif // KOLISEO_HAS_LOCATE
2213{
2214 if (kls == NULL) {
2215 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2216 exit(EXIT_FAILURE);
2217 }
2218 Koliseo* current = kls;
2219 while (current->next != NULL) {
2220 current = current->next;
2221 }
2222 if (current->has_temp != 0) {
2223 fprintf(stderr,
2224 "[ERROR] [%s()]: Passed Koliseo->has_temp is not 0. {%i}\n",
2225 __func__, current->has_temp);
2226#ifdef KLS_DEBUG_CORE
2227 kls_log(current, "ERROR", "[%s()]: Passed Koliseo->has_temp != 0 . {%i}",
2228 __func__, current->has_temp);
2229#endif
2230 return NULL;
2231 }
2232 ptrdiff_t prev = current->prev_offset;
2233 ptrdiff_t off = current->offset;
2234
2235 Koliseo_Temp *tmp = KLS_PUSH(current, Koliseo_Temp);
2236 tmp->kls = current;
2237 tmp->prev_offset = prev;
2238 tmp->offset = off;
2239#ifdef KLS_DEBUG_CORE
2240 kls_log(current, "INFO", "Passed kls conf: " KLS_Conf_Fmt "\n",
2241 KLS_Conf_Arg(current->conf));
2242#endif
2243
2244 current->has_temp = 1;
2245 current->t_kls = tmp;
2246 if (current->hooks.on_temp_start_handler != NULL) {
2247 // Call on_temp_start extension
2248 current->hooks.on_temp_start_handler(tmp);
2249 }
2250#ifdef KLS_DEBUG_CORE
2251 kls_log(current, "KLS", "Prepared new Temp KLS.");
2252#endif
2253 return tmp;
2254}
2255
2261{
2262 if (tmp_kls == NULL) {
2263 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo_Temp was NULL.\n",
2264 __func__);
2265 exit(EXIT_FAILURE);
2266 }
2267
2268 Koliseo *kls_ref = tmp_kls->kls;
2269 if (kls_ref == NULL) {
2270 fprintf(stderr, "[ERROR] [%s()]: Referred Koliseo was NULL.\n",
2271 __func__);
2272 exit(EXIT_FAILURE);
2273 }
2274
2275 if (kls_ref->hooks.on_temp_free_handler != NULL) {
2276 // Call on_temp_free() extension
2277 kls_ref->hooks.on_temp_free_handler(tmp_kls);
2278 }
2279
2280#ifdef KLS_DEBUG_CORE
2281 kls_log(kls_ref, "KLS", "Ended Temp KLS.");
2282#endif
2283 tmp_kls->kls->has_temp = 0;
2284 tmp_kls->kls->t_kls = NULL;
2285#if defined(__SANITIZE_ADDRESS__)
2286 ptrdiff_t old_offset = tmp_kls->kls->offset;
2287 ptrdiff_t new_offset = tmp_kls->offset;
2288#endif // __SANITIZE_ADDRESS__
2289 tmp_kls->kls->prev_offset = tmp_kls->prev_offset;
2290 tmp_kls->kls->offset = tmp_kls->offset;
2291
2292 // Free any Koliseo chained after the current one
2293 Koliseo* to_free = tmp_kls->kls->next;
2294 if (to_free != NULL) {
2295 kls_free(to_free);
2296 tmp_kls->kls->next = NULL;
2297 }
2298
2299 KLS_ASAN_POISON(tmp_kls->kls->data + new_offset, old_offset - new_offset);
2300 tmp_kls = NULL; // statement with no effect TODO: Clear tmp_kls from caller
2301 if (kls_ref->conf.collect_stats == 1) {
2302 kls_ref->stats.tot_temp_pushes = 0;
2303 kls_ref->stats.tot_temp_pops = 0;
2304 }
2305}
2306
2307#ifdef KOLISEO_HAS_EXPER
2316void *kls_pop(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
2317{
2318 if (kls == NULL) {
2319 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2320 exit(EXIT_FAILURE);
2321 }
2322 ptrdiff_t padding = -kls->offset & (align - 1);
2323 if (count > PTRDIFF_MAX / size
2324 || (kls->size + kls->offset) < (size * count)) {
2325 fprintf(stderr, "[KLS] Failed %s() call.\n", __func__);
2326 kls_free(kls);
2327 exit(EXIT_FAILURE);
2328 }
2329 char *p = kls->data + kls->offset - padding - size * count;
2330 kls->prev_offset = kls->offset;
2331 kls->offset -= padding + size * count;
2332#ifdef KLS_DEBUG_CORE
2333 kls_log(kls, "KLS", "Popped (%td) for KLS. Curr offset: { %p }",
2334 size, kls->data + kls->offset);
2335#endif
2336 if (kls->conf.collect_stats == 1) {
2337 kls->stats.tot_pops += 1;
2338 }
2339 return p;
2340}
2341
2350void *kls_temp_pop(Koliseo_Temp *t_kls, ptrdiff_t size, ptrdiff_t align,
2351 ptrdiff_t count)
2352{
2353 if (t_kls == NULL) {
2354 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo_Temp was NULL.\n",
2355 __func__);
2356 exit(EXIT_FAILURE);
2357 }
2358 Koliseo *kls = t_kls->kls;
2359 if (kls == NULL) {
2360 fprintf(stderr, "[ERROR] [%s()]: Referred Koliseo was NULL.\n",
2361 __func__);
2362 exit(EXIT_FAILURE);
2363 }
2364 ptrdiff_t padding = -kls->offset & (align - 1);
2365 if (count > PTRDIFF_MAX / size
2366 || (kls->size + kls->offset) < (size * count)) {
2367 fprintf(stderr, "[KLS] Failed %s() call.\n", __func__);
2368 kls_free(kls);
2369 exit(EXIT_FAILURE);
2370 }
2371 char *p = kls->data + kls->offset - padding - size * count;
2372 kls->prev_offset = kls->offset;
2373 kls->offset -= padding + size * count;
2374#ifdef KLS_DEBUG_CORE
2375 kls_log(kls, "KLS", "Popped (%td) for Temp_KLS. Curr offset: { %p }.", size, kls->data + kls->offset);
2376#endif
2377 if (kls->conf.collect_stats == 1) {
2378 kls->stats.tot_temp_pops += 1;
2379 }
2380 return p;
2381}
2382
2389char* kls_strdup(Koliseo* kls, char* source)
2390{
2391 char* dest = KLS_PUSH_STR(kls, source);
2392 KLS__STRCPY(dest, source);
2393 return dest;
2394}
2395
2402char** kls_strdup_arr(Koliseo* kls, size_t count, char** source)
2403{
2404 char** strings = NULL;
2405 strings = KLS_PUSH_ARR(kls, char*, count);
2406 for (int i=0; i < count; i++) {
2407 strings[i] = KLS_STRDUP(kls, source[i]);
2408 }
2409 return strings;
2410}
2411
2418char* kls_t_strdup(Koliseo_Temp* t_kls, char* source)
2419{
2420 char* dest = KLS_PUSH_STR_T(t_kls, source);
2421 KLS__STRCPY(dest, source);
2422 return dest;
2423}
2424
2431char** kls_t_strdup_arr(Koliseo_Temp* t_kls, size_t count, char** source)
2432{
2433 char** strings = NULL;
2434 strings = KLS_PUSH_ARR_T(t_kls, char*, count);
2435 for (int i=0; i < count; i++) {
2436 strings[i] = KLS_STRDUP_T(t_kls, source[i]);
2437 }
2438 return strings;
2439}
2440#endif // KOLISEO_HAS_EXPER
#define KLS_DEFAULT_HOOKS
Definition kls_region.h:164
Koliseo * kls_new_traced(ptrdiff_t size, const char *output_path)
Takes a ptrdiff_t size and a filepath for the trace output file.
Definition koliseo.c:851
Koliseo * kls_new(ptrdiff_t size)
Takes a ptrdiff_t size.
Definition koliseo.c:659
char * kls_strdup(Koliseo *kls, char *source)
Function to dupe a C string to a Koliseo, and return a pointer to the allocated string.
Definition koliseo.c:2389
void * kls_temp_pop(Koliseo_Temp *t_kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
Takes a Koliseo_Temp, and ptrdiff_t values for size, align and count.
Definition koliseo.c:2350
Koliseo_Temp * kls_temp_start(Koliseo *kls)
Starts a new savestate for the passed Koliseo pointer, by initialising its Koliseo_Temp pointer and r...
Definition koliseo.c:2209
void print_dbg_temp_kls(const Koliseo_Temp *t_kls)
Prints header fields from the passed Koliseo_Temp pointer, to stderr.
Definition koliseo.c:2071
void * kls_temp_repush(Koliseo_Temp *t_kls, void *old, ptrdiff_t size, ptrdiff_t align, ptrdiff_t old_count, ptrdiff_t new_count)
Takes a Koliseo_Temp pointer, and a void pointer to the old allocation, ptrdiff_t values for size,...
Definition koliseo.c:1814
Koliseo * kls_new_dbg_alloc(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func)
Takes a ptrdiff_t size, an allocation function pointer and a free function pointer,...
Definition koliseo.c:952
void print_temp_kls_2file(FILE *fp, const Koliseo_Temp *t_kls)
Prints header fields from the passed Koliseo_Temp pointer, to the passed FILE pointer.
Definition koliseo.c:2032
char * kls_t_strdup(Koliseo_Temp *t_kls, char *source)
Function to dupe a C string to a Koliseo_Temp, and return a pointer to the allocated string.
Definition koliseo.c:2418
Koliseo * kls_new_traced_alloc_handled(ptrdiff_t size, const char *output_path, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers)
Takes a ptrdiff_t size, a filepath for the trace output file, an allocation function pointer and a fr...
Definition koliseo.c:798
void kls_formatSize(size_t size, char *outputBuffer, size_t bufferSize)
Converts a ptrdiff_t size to human-readable SI units (modulo 1000).
Definition koliseo.c:2083
KLS_Stats KLS_STATS_DEFAULT
Default KLS_Stats values, used by kls_new().
Definition koliseo.c:46
void kls_log(Koliseo *kls, const char *tag, const char *format,...)
Logs a message to the log_fp FILE field of the passed Koliseo pointer, if its conf....
Definition koliseo.c:499
char * kls_vsprintf(Koliseo *kls, const char *fmt, va_list args)
Definition koliseo.c:1472
void kls_temp_end(Koliseo_Temp *tmp_kls)
Ends passed Koliseo_Temp pointer.
Definition koliseo.c:2260
void kls_dbg_features(void)
Prints enabled Koliseo features to stderr.
Definition koliseo.c:239
char ** kls_strdup_arr(Koliseo *kls, size_t count, char **source)
Function to dupe a C string array to a Koliseo, and return a pointer to the allocated array.
Definition koliseo.c:2402
void * kls_temp_push_zero_ext(Koliseo_Temp *t_kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
Takes a Koliseo_Temp, and ptrdiff_t values for size, align and count.
Definition koliseo.c:1525
void print_dbg_kls(const Koliseo *kls)
Prints header fields from the passed Koliseo pointer, to stderr.
Definition koliseo.c:2018
const char * string_koliseo_version(void)
Returns the constant string representing current version for Koliseo.
Definition koliseo.c:63
void * kls_repush(Koliseo *kls, void *old, ptrdiff_t size, ptrdiff_t align, ptrdiff_t old_count, ptrdiff_t new_count)
Takes a Koliseo pointer, and a void pointer to the old allocation, ptrdiff_t values for size,...
Definition koliseo.c:1631
KLS_Push_Result kls__advance(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t *padding, const char *caller_name)
Takes a Koliseo pointer, and ptrdiff_t values for size, align and count.
Definition koliseo.c:1106
char * kls_temp_vsprintf(Koliseo_Temp *kls_t, const char *fmt, va_list args)
Definition koliseo.c:1558
ptrdiff_t kls_get_pos(const Koliseo *kls)
Returns the current offset (position of pointer bumper) for the passed Koliseo.
Definition koliseo.c:292
Koliseo * kls_new_dbg_alloc_handled_ext(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size, an allocation function pointer and a free function pointer,...
Definition koliseo.c:886
#define KLS_ASAN_UNPOISON(addr, size)
Definition koliseo.c:83
void kls_free(Koliseo *kls)
Calls kls_clear() on the passed Koliseo pointer and the frees the actual Koliseo.
Definition koliseo.c:2139
KLS_Conf kls_conf_init_handled(int collect_stats, int verbose_lvl, int block_while_has_temp, int allow_zerocount_push, int growable, FILE *log_fp, const char *log_filepath, KLS_Err_Handlers err_handlers)
Used to prepare a KLS_Conf without caring about KOLISEO_HAS_REGIONS.
Definition koliseo.c:182
bool kls_contains_pointer(const Koliseo *kls, const void *ptr)
Takes a Koliseo pointer, and a void pointer to a memory region.
Definition koliseo.c:1605
Koliseo * kls_new_dbg_ext(ptrdiff_t size, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size.
Definition koliseo.c:935
char * kls_temp_sprintf(Koliseo_Temp *kls_t, const char *fmt,...)
Takes a Koliseo_Temp pointer, and a format cstring, plus varargs.
Definition koliseo.c:1584
char ** kls_t_strdup_arr(Koliseo_Temp *t_kls, size_t count, char **source)
Function to dupe a C string array to a Koliseo_Temp, and return a pointer to the allocated array.
Definition koliseo.c:2431
void * kls_push(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
Takes a Koliseo pointer, and ptrdiff_t values for size, align and count.
Definition koliseo.c:1367
Koliseo * kls_new_dbg_alloc_handled(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers)
Takes a ptrdiff_t size, an allocation function pointer and a free function pointer,...
Definition koliseo.c:920
KLS_Push_Error kls__check_available(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, const char *caller_name)
Takes a Koliseo, a ptrdiff_t size, align and count, and a caller name.
Definition koliseo.c:1201
#define KLS_ASAN_POISON(addr, size)
Definition koliseo.c:82
void * kls_push_zero(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
Takes a Koliseo pointer, and ptrdiff_t values for size, align and count.
Definition koliseo.c:1390
Koliseo * kls_new_alloc(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func)
Takes a ptrdiff_t size and a function pointer to the allocation function.
Definition koliseo.c:635
Koliseo * kls_new_dbg(ptrdiff_t size)
Takes a ptrdiff_t size and returns a pointer to the prepared Koliseo.
Definition koliseo.c:967
Koliseo * kls_new_traced_alloc(ptrdiff_t size, const char *output_path, kls_alloc_func alloc_func, kls_free_func free_func)
Takes a ptrdiff_t size, a filepath for the trace output file, an allocation function pointer and a fr...
Definition koliseo.c:834
char * kls_sprintf(Koliseo *kls, const char *fmt,...)
Takes a Koliseo pointer, and a format cstring, plus varargs.
Definition koliseo.c:1497
Koliseo * kls_new_traced_handled(ptrdiff_t size, const char *output_path, KLS_Err_Handlers err_handlers)
Takes a ptrdiff_t size and a filepath for the trace output file.
Definition koliseo.c:868
void * kls_pop(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
Takes a Koliseo pointer, and ptrdiff_t values for size, align and count.
Definition koliseo.c:2316
Koliseo * kls_new_conf_alloc_ext(ptrdiff_t size, KLS_Conf conf, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size, a KLS_Conf to configure the new Koliseo, an allocation function pointer and a...
Definition koliseo.c:680
void KLS_PTRDIFF_MAX_default_handler__(struct Koliseo *kls, ptrdiff_t size, ptrdiff_t count)
Used by default when no handler is passed.
Definition koliseo.c:116
KLS_Conf KLS_DEFAULT_CONF
Config used by any new Koliseo by default.
Definition koliseo.c:25
KLS_Conf kls_conf_init(int collect_stats, int verbose_lvl, int block_while_has_temp, int allow_zerocount_push, int growable, FILE *log_fp, const char *log_filepath)
Used to prepare a KLS_Conf without caring about KOLISEO_HAS_REGIONS.
Definition koliseo.c:230
void KLS_ZEROCOUNT_default_handler__(Koliseo *kls, ptrdiff_t available, ptrdiff_t padding, ptrdiff_t size)
Used internally for handling zero-count in push calls when no user handler is provided.
Definition koliseo.c:158
void * kls__handle_push_result(Koliseo *kls, KLS_Push_Result r, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t padding, const char *caller_name)
Handles a KLS_Push_Result.
Definition koliseo.c:310
Koliseo * kls_new_alloc_ext(ptrdiff_t size, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size and a function pointer to the allocation function.
Definition koliseo.c:545
void print_kls_2file(FILE *fp, const Koliseo *kls)
Prints header fields from the passed Koliseo pointer, to the passed FILE pointer.
Definition koliseo.c:1987
Koliseo * kls_new_traced_alloc_handled_ext(ptrdiff_t size, const char *output_path, kls_alloc_func alloc_func, kls_free_func free_func, KLS_Err_Handlers err_handlers, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size, a filepath for the trace output file, an allocation function pointer and a fr...
Definition koliseo.c:762
Koliseo * kls_new_dbg_handled(ptrdiff_t size, KLS_Err_Handlers err_handlers)
Takes a ptrdiff_t size and returns a pointer to the prepared Koliseo.
Definition koliseo.c:982
void kls_clear(Koliseo *kls)
Resets the offset field for the passed Koliseo pointer.
Definition koliseo.c:2107
void * kls_push_zero_ext(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
Takes a Koliseo pointer, and ptrdiff_t values for size, align and count.
Definition koliseo.c:1423
void KLS_OOM_default_handler__(Koliseo *kls, ptrdiff_t available, ptrdiff_t padding, ptrdiff_t size, ptrdiff_t count)
Used internally for handling Out-Of-Memory in push calls when no user handler is provided.
Definition koliseo.c:96
Koliseo * kls_new_conf_alloc(ptrdiff_t size, KLS_Conf conf, kls_alloc_func alloc_func, kls_free_func free_func)
Takes a ptrdiff_t size, a KLS_Conf to configure the new Koliseo, an allocation function pointer and a...
Definition koliseo.c:709
KLS_Push_Result kls__temp_advance(Koliseo_Temp *kls_t, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count, ptrdiff_t *padding, const char *caller_name)
Takes a Koliseo_Temp, and ptrdiff_t values for size, align and count.
Definition koliseo.c:1261
int int_koliseo_version(void)
Returns the constant int representing current version for Koliseo.
Definition koliseo.c:72
Koliseo * kls_new_traced_ext(ptrdiff_t size, const char *output_path, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size and a filepath for the trace output file.
Definition koliseo.c:815
Koliseo * kls_new_conf(ptrdiff_t size, KLS_Conf conf)
Takes a ptrdiff_t size and a KLS_Conf to configure the new Koliseo.
Definition koliseo.c:742
Koliseo * kls_new_conf_ext(ptrdiff_t size, KLS_Conf conf, KLS_Hooks ext_handlers, void *user)
Takes a ptrdiff_t size and a KLS_Conf to configure the new Koliseo.
Definition koliseo.c:726
void kls_free_func(void *)
Used to select a free function for the arena's backing memory.
Definition koliseo.h:92
#define KLS_PUSH_STR_T(kls_temp, cstr)
Macro to request memory for a C string from a Koliseo_Temp.
Definition koliseo.h:655
#define KLS_Stats_Fmt
Defines a format string for KLS_Stats.
Definition koliseo.h:299
#define KLS_PUSH_STR(kls, cstr)
Macro to request memory for a C string from a Koliseo.
Definition koliseo.h:538
#define KLS_Conf_Arg(conf)
Defines a format macro for KLS_Conf args.
Definition koliseo.h:292
#define KLS_DEFAULT_FREEF
Defines the default free function.
Definition koliseo.h:420
#define KLS_DEFAULT_ALLOCF
Defines the default allocation function.
Definition koliseo.h:416
#define KLS_PUSH(kls, type)
Macro used to request memory from a Koliseo.
Definition koliseo.h:575
#define KLS__STRCPY(dest, source)
Macro to copy a C string from a source buffer to a destination buffer.
Definition koliseo.h:759
#define KLS_ALIGNOF
Definition koliseo.h:24
#define KLS_DEFAULT_EXTENSION_DATA
Defines default hooks that are loaded on kls_new() variants lacking explicit set of KLS_Hooks.
Definition koliseo.h:226
void * kls_alloc_func(size_t)
Used to select an allocation function for the arena's backing memory.
Definition koliseo.h:91
#define KLS_MAX(a, b)
Definition koliseo.h:98
#define KLS_STRDUP(kls, source)
Definition koliseo.h:768
KLS_Push_Error
Defines the result for kls__check_available().
Definition koliseo.h:372
@ KLS_PUSH_NEGATIVE_COUNT
Definition koliseo.h:377
@ KLS_PUSH_ZEROCOUNT
Definition koliseo.h:378
@ KLS_PUSH_ALIGN_NOT_POW2
Definition koliseo.h:376
@ KLS_PUSH_WITH_TEMP_ACTIVE
Definition koliseo.h:379
@ KLS_PUSH_OOM
Definition koliseo.h:381
@ KLS_PUSH_PTRDIFF_MAX
Definition koliseo.h:380
@ KLS_PUSH_SIZE_LT1
Definition koliseo.h:374
@ KLS_PUSH_ALIGN_LT1
Definition koliseo.h:375
@ KLS_PUSH_OK
Definition koliseo.h:373
#define KLS_Stats_Arg(stats)
Defines a format macro for KLS_Stats args.
Definition koliseo.h:309
#define KLS_Conf_Fmt
Defines a format string for KLS_Conf.
Definition koliseo.h:286
#define KLS_PUSH_ARR_T(kls_temp, type, count)
Macro used to request memory for an array of type values from a Koliseo_Temp.
Definition koliseo.h:643
#define KLS_STRDUP_T(t_kls, source)
Definition koliseo.h:778
#define KLS_DEFAULT_ERR_HANDLERS
Definition koliseo.h:178
#define KLS_PUSH_ARR(kls, type, count)
Macro used to request memory for an array of type values from a Koliseo.
Definition koliseo.h:526
Defines flags for Koliseo.
Definition koliseo.h:233
int growable
If set to 1, make the Koliseo grow when a out of memory for a push call.
Definition koliseo.h:240
int verbose_lvl
If > 0, makes the Koliseo try to acquire kls_log_fp from kls_log_filepath.
Definition koliseo.h:235
const char * log_filepath
String representing the path to the Koliseo logfile.
Definition koliseo.h:237
FILE * log_fp
FILE pointer used by the Koliseo to print its kls_log() output.
Definition koliseo.h:236
int allow_zerocount_push
If set to 1, make the Koliseo accept push calls with a count of 0.
Definition koliseo.h:239
int collect_stats
If set to 1, make the Koliseo collect performance stats.
Definition koliseo.h:234
KLS_Err_Handlers err_handlers
Used to pass custom error handlers for push calls.
Definition koliseo.h:241
int block_while_has_temp
If set to 1, make the Koliseo reject push calls while it has an open Koliseo_Temp.
Definition koliseo.h:238
Defines the handlers used for errors in push calls.
Definition koliseo.h:171
KLS_OOM_Handler * OOM_handler
Pointer to handler for Out-Of-Memory errors in push calls.
Definition koliseo.h:172
KLS_ZEROCOUNT_Handler * ZEROCOUNT_handler
Pointer to handler for zero-count errors in push calls.
Definition koliseo.h:174
KLS_PTRDIFF_MAX_Handler * PTRDIFF_MAX_handler
Pointer to handler for count > (PTRDIFF_MAX / size) errors in push calls.
Definition koliseo.h:173
Definition koliseo.h:199
KLS_hook_on_temp_start * on_temp_start_handler
Used to pass custom start handler for kls_temp_start calls.
Definition koliseo.h:204
KLS_hook_on_free * on_free_handler
Used to pass custom free handler for kls_free calls.
Definition koliseo.h:201
KLS_hook_on_repush_last * on_repush_last_handler
Used to pass custom push handler for kls_repush calls that extend the last allocation (otherwise,...
Definition koliseo.h:203
KLS_hook_on_temp_free * on_temp_free_handler
Used to pass custom free handler for kls_temp_end calls.
Definition koliseo.h:205
KLS_hook_on_push * on_push_handler
Used to pass custom push handler for kls_push calls.
Definition koliseo.h:202
KLS_hook_on_new * on_new_handler
Used to pass custom new handler for kls_new_alloc calls.
Definition koliseo.h:200
KLS_hook_on_temp_push * on_temp_push_handler
Used to pass custom push handler for kls_temp_push calls.
Definition koliseo.h:206
KLS_hook_on_temp_repush_last * on_temp_repush_last_handler
Used to pass custom push handler for kls_temp_repush calls that extend the last allocation (otherwise...
Definition koliseo.h:207
Defines the result for kls__advance() and kls__temp_advance().
Definition koliseo.h:389
KLS_Push_Error error
Definition koliseo.h:391
void * p
Definition koliseo.h:390
Defines a stat struct for Koliseo.
Definition koliseo.h:254
int tot_pops
Total POP calls done.
Definition koliseo.h:257
double worst_pushcall_time
DEPRECATED: support for timing will be dropped in the next release.
Definition koliseo.h:264
int tot_temp_pushes
Total PUSH_T calls done.
Definition koliseo.h:256
int tot_pushes
Total PUSH calls done.
Definition koliseo.h:255
int tot_temp_pops
Total POP_T calls done.
Definition koliseo.h:258
Represents a savestate for a Koliseo.
Definition koliseo.h:361
ptrdiff_t offset
Current position of memory pointer.
Definition koliseo.h:363
ptrdiff_t prev_offset
Previous position of memory pointer.
Definition koliseo.h:364
Koliseo * kls
Reference to the actual Koliseo we're saving.
Definition koliseo.h:362
Represents the initialised arena allocator struct.
Definition koliseo.h:322
ptrdiff_t size
Size of data field.
Definition koliseo.h:324
ptrdiff_t offset
Current position of memory pointer.
Definition koliseo.h:325
ptrdiff_t prev_offset
Previous position of memory pointer.
Definition koliseo.h:326
KLS_Conf conf
Contains flags to change the Koliseo behaviour.
Definition koliseo.h:328
struct Koliseo_Temp * t_kls
Points to related active Kolieo_Temp, when has_temp == 1.
Definition koliseo.h:330
KLS_Hooks hooks
Contains handlers for extensions.
Definition koliseo.h:331
char * data
Points to data field.
Definition koliseo.h:323
struct Koliseo * next
Points to the next Koliseo when conf.growable == 1.
Definition koliseo.h:335
void * extension_data
Points to data for extensions.
Definition koliseo.h:332
int has_temp
When == 1, a Koliseo_Temp is currently active on this Koliseo.
Definition koliseo.h:327
KLS_Stats stats
Contains stats for Koliseo performance analysis.
Definition koliseo.h:329
kls_free_func * free_func
Points to the free function for the arena's backing memory.
Definition koliseo.h:334