koliseo 0.6.3
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 } else {
1788#ifdef KLS_DEBUG_CORE
1789 kls_log(current, "KLS", "%s(): pushed new memory", __func__);
1790#endif
1791 new_ptr = kls_push_zero_ext(kls, size, align, new_count);
1792 if (new_ptr && old_size > 0) {
1793 memcpy(new_ptr, old, old_size);
1794 }
1795 }
1796 return new_ptr;
1797}
1798
1810#ifndef KOLISEO_HAS_LOCATE
1811void *kls_temp_repush(Koliseo_Temp *t_kls, void* old, ptrdiff_t size, ptrdiff_t align,
1812 ptrdiff_t old_count, ptrdiff_t new_count)
1813#else
1814void *kls_temp_repush_dbg(Koliseo_Temp *t_kls, void* old, ptrdiff_t size, ptrdiff_t align,
1815 ptrdiff_t old_count, ptrdiff_t new_count, Koliseo_Loc loc)
1816#endif // KOLISEO_HAS_LOCATE
1817{
1818 if (!old) {
1819#ifndef KOLISEO_HAS_LOCATE
1820 fprintf(stderr,
1821 "[KLS] %s(): old was NULL.\n",
1822 __func__);
1823#else
1824 fprintf(stderr,
1825 "[KLS] " KLS_Loc_Fmt "%s(): old was NULL.\n",
1826 KLS_Loc_Arg(loc),
1827 __func__);
1828#endif // KOLISEO_HAS_LOCATE
1829 return NULL;
1830 }
1831 if (!kls_contains_pointer(t_kls->kls, old)) {
1832 fprintf(stderr,
1833 "[KLS] %s(): pointer %p does not belong to this Koliseo.\n",
1834 __func__,
1835 old);
1836 return NULL;
1837 }
1838 if (old_count < 0) {
1839#ifndef KOLISEO_HAS_LOCATE
1840 fprintf(stderr,
1841 "[KLS] %s(): old_count [%td] was < 0.\n",
1842 __func__,
1843 old_count);
1844#else
1845 fprintf(stderr,
1846 "[KLS] " KLS_Loc_Fmt "%s(): old_count [%td] was < 0.\n",
1847 KLS_Loc_Arg(loc),
1848 __func__,
1849 old_count);
1850#endif // KOLISEO_HAS_LOCATE
1851 return NULL;
1852 }
1853 if (new_count < 0) {
1854#ifndef KOLISEO_HAS_LOCATE
1855 fprintf(stderr,
1856 "[KLS] %s(): new_count [%td] was < 0.\n",
1857 __func__,
1858 new_count);
1859#else
1860 fprintf(stderr,
1861 "[KLS] " KLS_Loc_Fmt "%s(): new_count [%td] was < 0.\n",
1862 KLS_Loc_Arg(loc),
1863 __func__,
1864 new_count);
1865#endif // KOLISEO_HAS_LOCATE
1866 return NULL;
1867 }
1868 if (size < 1) {
1869#ifndef KOLISEO_HAS_LOCATE
1870 fprintf(stderr,
1871 "[KLS] %s(): size [%td] was < 1.\n",
1872 __func__,
1873 size);
1874#else
1875 fprintf(stderr,
1876 "[KLS] " KLS_Loc_Fmt "%s(): size [%td] was < 1.\n",
1877 KLS_Loc_Arg(loc),
1878 __func__,
1879 size);
1880#endif // KOLISEO_HAS_LOCATE
1881 return NULL;
1882 }
1883 if (align < 1) {
1884#ifndef KOLISEO_HAS_LOCATE
1885 fprintf(stderr,
1886 "[KLS] %s(): align [%td] was < 1.\n",
1887 __func__,
1888 align);
1889#else
1890 fprintf(stderr,
1891 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was < 1.\n",
1892 KLS_Loc_Arg(loc),
1893 __func__,
1894 align);
1895#endif // KOLISEO_HAS_LOCATE
1896 return NULL;
1897 }
1898 if (! ((align & (align - 1)) == 0)) {
1899#ifndef KOLISEO_HAS_LOCATE
1900 fprintf(stderr,
1901 "[KLS] %s(): align [%td] was not a power of 2.\n",
1902 __func__,
1903 align);
1904#else
1905 fprintf(stderr,
1906 "[KLS] " KLS_Loc_Fmt "%s(): align [%td] was not a power of 2.\n",
1907 KLS_Loc_Arg(loc),
1908 __func__,
1909 align);
1910#endif // KOLISEO_HAS_LOCATE
1911 return NULL;
1912 }
1913
1914 if (old_count >= new_count) return old;
1915
1916 ptrdiff_t growth = new_count - old_count;
1917
1918 if ((size_t)old_count > SIZE_MAX / (size_t)size) return NULL;
1919
1920 if ((size_t)new_count > SIZE_MAX / (size_t)size) return NULL;
1921
1922 size_t old_size = (size_t)old_count * (size_t)size;
1923 size_t new_size = (size_t)new_count * (size_t)size;
1924
1925 Koliseo* current = t_kls->kls;
1926 while (current->next != NULL) {
1927 current = current->next;
1928 }
1929
1930 ptrdiff_t padding = 0;
1931 bool is_last_alloc = old == (current->data + current->prev_offset);
1932
1933 void* new_ptr = NULL;
1934 if (is_last_alloc) {
1935 // Extend last allocation
1936
1937 // Save prev_offset
1938 const ptrdiff_t saved_prev_offset = current->prev_offset;
1939#ifndef KOLISEO_HAS_LOCATE
1940 KLS_Push_Result res = kls__temp_advance(t_kls, size, align, growth, &padding, __func__);
1941 void* p = kls__handle_push_result(current, res, size, align, growth, padding, __func__);
1942#else
1943 KLS_Push_Result res = kls__temp_advance_dbg(t_kls, size, align, growth, &padding, __func__, loc);
1944 void* p = kls__handle_push_result_dbg(current, res, size, align, growth, padding, __func__, loc);
1945#endif // KOLISEO_HAS_LOCATE
1946 if (!p) return NULL;
1947 size_t added_size = new_size - old_size;
1948 //Zero new area
1949 memset(p, 0, added_size);
1950 new_ptr = old;
1951
1952 Koliseo* new_current = current;
1953 while (new_current->next != NULL) {
1954 new_current = new_current->next;
1955 }
1956
1957#ifdef KLS_DEBUG_CORE
1958 const ptrdiff_t new_byte_slice_len = new_current->offset - new_current->prev_offset + padding;
1959 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);
1960#endif
1961
1962 // Restore saved prev_offset
1963 current->prev_offset = saved_prev_offset;
1964 } else {
1965#ifdef KLS_DEBUG_CORE
1966 kls_log(current, "KLS", "%s(): pushed new memory", __func__);
1967#endif
1968 new_ptr = kls_temp_push_zero_ext(t_kls, size, align, new_count);
1969 if (new_ptr && old_size > 0) {
1970 memcpy(new_ptr, old, old_size);
1971 }
1972 }
1973 return new_ptr;
1974}
1975
1981void print_kls_2file(FILE *fp, const Koliseo *kls)
1982{
1983 if (fp == NULL) {
1984 fprintf(stderr, "print_kls_2file(): fp was NULL.\n");
1985 return;
1986 }
1987 if (kls == NULL) {
1988 fprintf(fp, "[KLS] kls was NULL.\n");
1989 } else {
1990 fprintf(fp, "\n[KLS] API Level: { %i }\n", int_koliseo_version());
1991 fprintf(fp, "\n[INFO] Conf: { " KLS_Conf_Fmt " }\n",
1992 KLS_Conf_Arg(kls->conf));
1993 fprintf(fp, "\n[INFO] Stats: { " KLS_Stats_Fmt " }\n",
1994 KLS_Stats_Arg(kls->stats));
1995 fprintf(fp, "\n[KLS] Size: { %td }\n", kls->size);
1996 char human_size[200];
1997 char curr_size[200];
1998 kls_formatSize(kls->size, human_size, sizeof(human_size));
1999 fprintf(fp, "[KLS] Size (Human): { %s }\n", human_size);
2000 kls_formatSize(kls->offset, curr_size, sizeof(curr_size));
2001 fprintf(fp, "[KLS] Used (Human): { %s }\n", curr_size);
2002 fprintf(fp, "[KLS] Offset: { %td }\n", kls->offset);
2003 fprintf(fp, "[KLS] Prev_Offset: { %td }\n", kls->prev_offset);
2004 fprintf(fp, "\n");
2005 }
2006}
2007
2012void print_dbg_kls(const Koliseo *kls)
2013{
2014 if (kls == NULL) {
2015 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2016 exit(EXIT_FAILURE);
2017 }
2018 print_kls_2file(stderr, kls);
2019}
2020
2026void print_temp_kls_2file(FILE *fp, const Koliseo_Temp *t_kls)
2027{
2028 if (fp == NULL) {
2029 fprintf(stderr, "print_temp_kls_2file(): fp was NULL.\n");
2030 exit(EXIT_FAILURE);
2031 }
2032 if (t_kls == NULL) {
2033 fprintf(fp, "[KLS_T] t_kls was NULL.");
2034 } else if (t_kls->kls == NULL) {
2035 fprintf(fp, "[KLS_T] [%s()]: Referred Koliseo was NULL.\n", __func__);
2036 } else {
2037 const Koliseo *kls = t_kls->kls;
2038 fprintf(fp, "\n[KLS_T] API Level: { %i }\n", int_koliseo_version());
2039 fprintf(fp, "\n[KLS_T] Temp Size: { %td }\n",
2040 kls->size - t_kls->offset);
2041 fprintf(fp, "\n[KLS_T] Refer Size: { %td }\n", kls->size);
2042 char human_size[200];
2043 char curr_size[200];
2044 kls_formatSize(kls->size - t_kls->offset, human_size,
2045 sizeof(human_size));
2046 fprintf(fp, "[KLS_T] Temp Size Human: { %s }\n", human_size);
2047 kls_formatSize(kls->size, human_size, sizeof(human_size));
2048 fprintf(fp, "[KLS_T] Refer Size Human: { %s }\n", human_size);
2049 kls_formatSize(kls->offset, curr_size, sizeof(curr_size));
2050 fprintf(fp, "[KLS_T] Inner Used (Human): { %s }\n", curr_size);
2051 kls_formatSize(t_kls->offset, curr_size, sizeof(curr_size));
2052 fprintf(fp, "[KLS_T] Temp Used (Human): { %s }\n", curr_size);
2053 fprintf(fp, "[KLS_T] Inner Offset: { %td }\n", kls->offset);
2054 fprintf(fp, "[KLS_T] Temp Offset: { %td }\n", t_kls->offset);
2055 fprintf(fp, "[KLS_T] Inner Prev_Offset: { %td }\n", kls->prev_offset);
2056 fprintf(fp, "[KLS_T] Temp Prev_Offset: { %td }\n\n",
2057 t_kls->prev_offset);
2058 }
2059}
2060
2066{
2067 print_temp_kls_2file(stderr, t_kls);
2068}
2069
2077void kls_formatSize(size_t size, char *outputBuffer, size_t bufferSize)
2078{
2079 static const char *units[] = {
2080 "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
2081 };
2082
2083 const int numUnits = sizeof(units) / sizeof(units[0]);
2084
2085 size_t unitIndex = 0;
2086 long double sizeValue = (long double)size;
2087
2088 while (sizeValue >= 1000 && unitIndex < numUnits - 1) {
2089 sizeValue /= 1000;
2090 unitIndex++;
2091 }
2092
2093 snprintf(outputBuffer, bufferSize, "%.2Lf %s", sizeValue, units[unitIndex]);
2094}
2095
2102{
2103 if (kls == NULL) {
2104 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2105 exit(EXIT_FAILURE);
2106 }
2107 //Reset pointer
2108 kls->prev_offset = kls->offset;
2109 kls->offset = sizeof(*kls);
2110 if (kls->next) {
2111 Koliseo *chain = kls->next;
2112 kls->next = NULL;
2113 if (chain) {
2114 kls_free(chain);
2115 kls->extension_data = NULL; // The chain shares this pointer and we need to restore the extension data
2116 if (kls->hooks.on_new_handler) {
2117 kls->hooks.on_new_handler(kls);
2118 }
2119 }
2120 }
2121 KLS_ASAN_POISON(kls->data + kls->offset, kls->size - kls->offset);
2122#ifdef KLS_DEBUG_CORE
2123 kls_log(kls, "KLS", "API Level { %i } -> Cleared offsets for KLS.",
2125#endif
2126}
2127
2134{
2135 if (kls == NULL) {
2136 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2137 exit(EXIT_FAILURE);
2138 }
2139 Koliseo* current = kls;
2140 while (current) {
2141 if (current->has_temp == 1) {
2142#ifdef KLS_DEBUG_CORE
2143 kls_log(current, "KLS",
2144 "API Level { %i } -> KLS had an active Koliseo_Temp.",
2146#endif
2147 kls_temp_end(current->t_kls);
2148 }
2149 if (current->hooks.on_free_handler != NULL) {
2150 // Call on_free() extension
2151 current->hooks.on_free_handler(current);
2152 for (Koliseo *k = current; k; k = k->next) {
2153 // We NULL all subsequent extension_data pointers, since the chain shares it
2154 // and it's freed in the first hook call
2155 k->extension_data = NULL;
2156 }
2157 }
2158 Koliseo* next = current->next;
2159 current->next = NULL;
2160 //kls_clear(current);
2161#ifdef KLS_DEBUG_CORE
2162 kls_log(current, "KLS", "API Level { %i } -> Freeing KLS.",
2164#endif
2165 if (current->conf.log_fp != NULL && current->conf.log_fp != stdout
2166 && current->conf.log_fp != stderr) {
2167#ifdef KLS_DEBUG_CORE
2168 kls_log(current, "KLS", "Closing kls log file. Path: {\"%s\"}.",
2169 kls->conf.log_filepath);
2170#endif
2171 int close_res = fclose(current->conf.log_fp);
2172 if (close_res != 0) {
2173 fprintf(stderr,
2174 "[ERROR] %s(): Failed fclose() on log_fp. Path: {\"%s\"}.",
2175 __func__, current->conf.log_filepath);
2176 }
2177 } else if (current->conf.log_fp == stdout || current->conf.log_fp == stderr) {
2178 if (current->conf.verbose_lvl > 1) {
2179 fprintf(stderr,
2180 "[INFO] %s(): kls->conf.log_fp is %s. Not closing it.\n",
2181 __func__,
2182 (current->conf.log_fp == stdout ? "stdout" : "stderr"));
2183 }
2184 }
2185 if (current->free_func == NULL) {
2186 fprintf(stderr,
2187 "[ERROR] %s(): free function was NULL.\n", __func__);
2188 return;
2189 }
2190 current->free_func(current);
2191 current = next;
2192 }
2193}
2194
2202#ifndef KOLISEO_HAS_LOCATE
2204#else
2205Koliseo_Temp *kls_temp_start_dbg(Koliseo *kls, Koliseo_Loc loc)
2206#endif // KOLISEO_HAS_LOCATE
2207{
2208 if (kls == NULL) {
2209 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2210 exit(EXIT_FAILURE);
2211 }
2212 Koliseo* current = kls;
2213 while (current->next != NULL) {
2214 current = current->next;
2215 }
2216 if (current->has_temp != 0) {
2217 fprintf(stderr,
2218 "[ERROR] [%s()]: Passed Koliseo->has_temp is not 0. {%i}\n",
2219 __func__, current->has_temp);
2220#ifdef KLS_DEBUG_CORE
2221 kls_log(current, "ERROR", "[%s()]: Passed Koliseo->has_temp != 0 . {%i}",
2222 __func__, current->has_temp);
2223#endif
2224 return NULL;
2225 }
2226 ptrdiff_t prev = current->prev_offset;
2227 ptrdiff_t off = current->offset;
2228
2229 Koliseo_Temp *tmp = KLS_PUSH(current, Koliseo_Temp);
2230 tmp->kls = current;
2231 tmp->prev_offset = prev;
2232 tmp->offset = off;
2233#ifdef KLS_DEBUG_CORE
2234 kls_log(current, "INFO", "Passed kls conf: " KLS_Conf_Fmt "\n",
2235 KLS_Conf_Arg(current->conf));
2236#endif
2237
2238 current->has_temp = 1;
2239 current->t_kls = tmp;
2240 if (current->hooks.on_temp_start_handler != NULL) {
2241 // Call on_temp_start extension
2242 current->hooks.on_temp_start_handler(tmp);
2243 }
2244#ifdef KLS_DEBUG_CORE
2245 kls_log(current, "KLS", "Prepared new Temp KLS.");
2246#endif
2247 return tmp;
2248}
2249
2255{
2256 if (tmp_kls == NULL) {
2257 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo_Temp was NULL.\n",
2258 __func__);
2259 exit(EXIT_FAILURE);
2260 }
2261
2262 Koliseo *kls_ref = tmp_kls->kls;
2263 if (kls_ref == NULL) {
2264 fprintf(stderr, "[ERROR] [%s()]: Referred Koliseo was NULL.\n",
2265 __func__);
2266 exit(EXIT_FAILURE);
2267 }
2268
2269 if (kls_ref->hooks.on_temp_free_handler != NULL) {
2270 // Call on_temp_free() extension
2271 kls_ref->hooks.on_temp_free_handler(tmp_kls);
2272 }
2273
2274#ifdef KLS_DEBUG_CORE
2275 kls_log(kls_ref, "KLS", "Ended Temp KLS.");
2276#endif
2277 tmp_kls->kls->has_temp = 0;
2278 tmp_kls->kls->t_kls = NULL;
2279#if defined(__SANITIZE_ADDRESS__)
2280 ptrdiff_t old_offset = tmp_kls->kls->offset;
2281 ptrdiff_t new_offset = tmp_kls->offset;
2282#endif // __SANITIZE_ADDRESS__
2283 tmp_kls->kls->prev_offset = tmp_kls->prev_offset;
2284 tmp_kls->kls->offset = tmp_kls->offset;
2285
2286 // Free any Koliseo chained after the current one
2287 Koliseo* to_free = tmp_kls->kls->next;
2288 if (to_free != NULL) {
2289 kls_free(to_free);
2290 tmp_kls->kls->next = NULL;
2291 }
2292
2293 KLS_ASAN_POISON(tmp_kls->kls->data + new_offset, old_offset - new_offset);
2294 tmp_kls = NULL; // statement with no effect TODO: Clear tmp_kls from caller
2295 if (kls_ref->conf.collect_stats == 1) {
2296 kls_ref->stats.tot_temp_pushes = 0;
2297 kls_ref->stats.tot_temp_pops = 0;
2298 }
2299}
2300
2301#ifdef KOLISEO_HAS_EXPER
2310void *kls_pop(Koliseo *kls, ptrdiff_t size, ptrdiff_t align, ptrdiff_t count)
2311{
2312 if (kls == NULL) {
2313 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo was NULL.\n", __func__);
2314 exit(EXIT_FAILURE);
2315 }
2316 ptrdiff_t padding = -kls->offset & (align - 1);
2317 if (count > PTRDIFF_MAX / size
2318 || (kls->size + kls->offset) < (size * count)) {
2319 fprintf(stderr, "[KLS] Failed %s() call.\n", __func__);
2320 kls_free(kls);
2321 exit(EXIT_FAILURE);
2322 }
2323 char *p = kls->data + kls->offset - padding - size * count;
2324 kls->prev_offset = kls->offset;
2325 kls->offset -= padding + size * count;
2326#ifdef KLS_DEBUG_CORE
2327 kls_log(kls, "KLS", "Popped (%td) for KLS. Curr offset: { %p }",
2328 size, kls->data + kls->offset);
2329#endif
2330 if (kls->conf.collect_stats == 1) {
2331 kls->stats.tot_pops += 1;
2332 }
2333 return p;
2334}
2335
2344void *kls_temp_pop(Koliseo_Temp *t_kls, ptrdiff_t size, ptrdiff_t align,
2345 ptrdiff_t count)
2346{
2347 if (t_kls == NULL) {
2348 fprintf(stderr, "[ERROR] [%s()]: Passed Koliseo_Temp was NULL.\n",
2349 __func__);
2350 exit(EXIT_FAILURE);
2351 }
2352 Koliseo *kls = t_kls->kls;
2353 if (kls == NULL) {
2354 fprintf(stderr, "[ERROR] [%s()]: Referred Koliseo was NULL.\n",
2355 __func__);
2356 exit(EXIT_FAILURE);
2357 }
2358 ptrdiff_t padding = -kls->offset & (align - 1);
2359 if (count > PTRDIFF_MAX / size
2360 || (kls->size + kls->offset) < (size * count)) {
2361 fprintf(stderr, "[KLS] Failed %s() call.\n", __func__);
2362 kls_free(kls);
2363 exit(EXIT_FAILURE);
2364 }
2365 char *p = kls->data + kls->offset - padding - size * count;
2366 kls->prev_offset = kls->offset;
2367 kls->offset -= padding + size * count;
2368#ifdef KLS_DEBUG_CORE
2369 kls_log(kls, "KLS", "Popped (%td) for Temp_KLS. Curr offset: { %p }.", size, kls->data + kls->offset);
2370#endif
2371 if (kls->conf.collect_stats == 1) {
2372 kls->stats.tot_temp_pops += 1;
2373 }
2374 return p;
2375}
2376
2383char* kls_strdup(Koliseo* kls, char* source)
2384{
2385 char* dest = KLS_PUSH_STR(kls, source);
2386 KLS__STRCPY(dest, source);
2387 return dest;
2388}
2389
2396char** kls_strdup_arr(Koliseo* kls, size_t count, char** source)
2397{
2398 char** strings = NULL;
2399 strings = KLS_PUSH_ARR(kls, char*, count);
2400 for (int i=0; i < count; i++) {
2401 strings[i] = KLS_STRDUP(kls, source[i]);
2402 }
2403 return strings;
2404}
2405
2412char* kls_t_strdup(Koliseo_Temp* t_kls, char* source)
2413{
2414 char* dest = KLS_PUSH_STR_T(t_kls, source);
2415 KLS__STRCPY(dest, source);
2416 return dest;
2417}
2418
2425char** kls_t_strdup_arr(Koliseo_Temp* t_kls, size_t count, char** source)
2426{
2427 char** strings = NULL;
2428 strings = KLS_PUSH_ARR_T(t_kls, char*, count);
2429 for (int i=0; i < count; i++) {
2430 strings[i] = KLS_STRDUP_T(t_kls, source[i]);
2431 }
2432 return strings;
2433}
2434#endif // KOLISEO_HAS_EXPER
#define KLS_DEFAULT_HOOKS
Definition kls_region.h:162
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:2383
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:2344
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:2203
void print_dbg_temp_kls(const Koliseo_Temp *t_kls)
Prints header fields from the passed Koliseo_Temp pointer, to stderr.
Definition koliseo.c:2065
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:1811
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:2026
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:2412
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:2077
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:2254
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:2396
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:2012
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:2133
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:2425
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:2310
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:1981
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:2101
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:649
#define KLS_Stats_Fmt
Defines a format string for KLS_Stats.
Definition koliseo.h:293
#define KLS_PUSH_STR(kls, cstr)
Macro to request memory for a C string from a Koliseo.
Definition koliseo.h:532
#define KLS_Conf_Arg(conf)
Defines a format macro for KLS_Conf args.
Definition koliseo.h:286
#define KLS_DEFAULT_FREEF
Defines the default free function.
Definition koliseo.h:414
#define KLS_DEFAULT_ALLOCF
Defines the default allocation function.
Definition koliseo.h:410
#define KLS_PUSH(kls, type)
Macro used to request memory from a Koliseo.
Definition koliseo.h:569
#define KLS__STRCPY(dest, source)
Macro to copy a C string from a source buffer to a destination buffer.
Definition koliseo.h:753
#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:220
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:762
KLS_Push_Error
Defines the result for kls__check_available().
Definition koliseo.h:366
@ KLS_PUSH_NEGATIVE_COUNT
Definition koliseo.h:371
@ KLS_PUSH_ZEROCOUNT
Definition koliseo.h:372
@ KLS_PUSH_ALIGN_NOT_POW2
Definition koliseo.h:370
@ KLS_PUSH_WITH_TEMP_ACTIVE
Definition koliseo.h:373
@ KLS_PUSH_OOM
Definition koliseo.h:375
@ KLS_PUSH_PTRDIFF_MAX
Definition koliseo.h:374
@ KLS_PUSH_SIZE_LT1
Definition koliseo.h:368
@ KLS_PUSH_ALIGN_LT1
Definition koliseo.h:369
@ KLS_PUSH_OK
Definition koliseo.h:367
#define KLS_Stats_Arg(stats)
Defines a format macro for KLS_Stats args.
Definition koliseo.h:303
#define KLS_Conf_Fmt
Defines a format string for KLS_Conf.
Definition koliseo.h:280
#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:637
#define KLS_STRDUP_T(t_kls, source)
Definition koliseo.h:772
#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:520
Defines flags for Koliseo.
Definition koliseo.h:227
int growable
If set to 1, make the Koliseo grow when a out of memory for a push call.
Definition koliseo.h:234
int verbose_lvl
If > 0, makes the Koliseo try to acquire kls_log_fp from kls_log_filepath.
Definition koliseo.h:229
const char * log_filepath
String representing the path to the Koliseo logfile.
Definition koliseo.h:231
FILE * log_fp
FILE pointer used by the Koliseo to print its kls_log() output.
Definition koliseo.h:230
int allow_zerocount_push
If set to 1, make the Koliseo accept push calls with a count of 0.
Definition koliseo.h:233
int collect_stats
If set to 1, make the Koliseo collect performance stats.
Definition koliseo.h:228
KLS_Err_Handlers err_handlers
Used to pass custom error handlers for push calls.
Definition koliseo.h:235
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:232
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:195
KLS_hook_on_temp_start * on_temp_start_handler
Used to pass custom start handler for kls_temp_start calls.
Definition koliseo.h:199
KLS_hook_on_free * on_free_handler
Used to pass custom free handler for kls_free calls.
Definition koliseo.h:197
KLS_hook_on_temp_free * on_temp_free_handler
Used to pass custom free handler for kls_temp_end calls.
Definition koliseo.h:200
KLS_hook_on_push * on_push_handler
Used to pass custom push handler for kls_push calls.
Definition koliseo.h:198
KLS_hook_on_new * on_new_handler
Used to pass custom new handler for kls_new_alloc calls.
Definition koliseo.h:196
KLS_hook_on_temp_push * on_temp_push_handler
Used to pass custom push handler for kls_temp_push calls.
Definition koliseo.h:201
Defines the result for kls__advance() and kls__temp_advance().
Definition koliseo.h:383
KLS_Push_Error error
Definition koliseo.h:385
void * p
Definition koliseo.h:384
Defines a stat struct for Koliseo.
Definition koliseo.h:248
int tot_pops
Total POP calls done.
Definition koliseo.h:251
double worst_pushcall_time
DEPRECATED: support for timing will be dropped in the next release.
Definition koliseo.h:258
int tot_temp_pushes
Total PUSH_T calls done.
Definition koliseo.h:250
int tot_pushes
Total PUSH calls done.
Definition koliseo.h:249
int tot_temp_pops
Total POP_T calls done.
Definition koliseo.h:252
Represents a savestate for a Koliseo.
Definition koliseo.h:355
ptrdiff_t offset
Current position of memory pointer.
Definition koliseo.h:357
ptrdiff_t prev_offset
Previous position of memory pointer.
Definition koliseo.h:358
Koliseo * kls
Reference to the actual Koliseo we're saving.
Definition koliseo.h:356
Represents the initialised arena allocator struct.
Definition koliseo.h:316
ptrdiff_t size
Size of data field.
Definition koliseo.h:318
ptrdiff_t offset
Current position of memory pointer.
Definition koliseo.h:319
ptrdiff_t prev_offset
Previous position of memory pointer.
Definition koliseo.h:320
KLS_Conf conf
Contains flags to change the Koliseo behaviour.
Definition koliseo.h:322
struct Koliseo_Temp * t_kls
Points to related active Kolieo_Temp, when has_temp == 1.
Definition koliseo.h:324
KLS_Hooks hooks
Contains handlers for extensions.
Definition koliseo.h:325
char * data
Points to data field.
Definition koliseo.h:317
struct Koliseo * next
Points to the next Koliseo when conf.growable == 1.
Definition koliseo.h:329
void * extension_data
Points to data for extensions.
Definition koliseo.h:326
int has_temp
When == 1, a Koliseo_Temp is currently active on this Koliseo.
Definition koliseo.h:321
KLS_Stats stats
Contains stats for Koliseo performance analysis.
Definition koliseo.h:323
kls_free_func * free_func
Points to the free function for the arena's backing memory.
Definition koliseo.h:328