From 5625a8626fe303748b205c80f87035593cf2f561 Mon Sep 17 00:00:00 2001 From: iamcheeseman Date: Fri, 8 May 2026 19:30:44 -0400 Subject: Initial commit --- teensy/mem.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 teensy/mem.c (limited to 'teensy/mem.c') diff --git a/teensy/mem.c b/teensy/mem.c new file mode 100644 index 0000000..2c938a6 --- /dev/null +++ b/teensy/mem.c @@ -0,0 +1,171 @@ +#include "mem.h" + +#include "common.h" +#include "dyn_arr.h" + +// Array to track temp allocations. +void **temp_allocations; + +#ifdef TEENSY_DEBUG + +#include + +#define BACKTRACE_SIZE 16 + +struct alloc { + void *ptr; + size_t size; + int backtrace_len; + char **backtrace; +}; + +int allocations_cap; +int allocations_len; +struct alloc *allocations; + +#endif // TODO TEENSY_DEBUG + +void ty_init_mem(void) +{ +#ifdef TEENSY_DEBUG + allocations_len = 0; + allocations_cap = 8; + allocations = malloc(sizeof(struct alloc) * 8); + if (!allocations) + ty_log_fatal(TY_ERR_MEM, "(%s) (track) ran out of memory", __func__); +#endif // TEENSY_DEBUG + + temp_allocations = ty_list_create(void*, 0); +} + +void ty_deinit_mem(void) +{ + ty_list_free(temp_allocations); +#ifdef TEENSY_DEBUG + fprintf(stderr, "%d allocations leaked\n", allocations_len); + for (int i = 0; i < allocations_len; i++) { + struct alloc *alloc = &allocations[i]; + fprintf( + stderr, + "leaked %zu bytes at %p\n", + alloc->size, + alloc->ptr + ); + for (int j = 0; j < alloc->backtrace_len; j++) { + fprintf(stderr, "\t%s\n", alloc->backtrace[j]); + } + putc('\n', stderr); + + free(alloc->backtrace); + } + free(allocations); + + if (allocations_len > 0) + exit(TY_ERR_MEM_LEAK); +#endif // TEENSY_DEBUG +} + +void ty_free_temp_allocs(void) +{ + for (int i = 0; i < ty_list_len(temp_allocations); i++) { + void *temp = temp_allocations[i]; + ty_free(temp); + } + ty_list_clear(temp_allocations); +} + +void *ty_alloc(size_t size) +{ + void *ptr = malloc(size); + if (!ptr) + ty_log_fatal(TY_ERR_MEM, "(%s) ran out of memory", __func__); + +#ifdef TEENSY_DEBUG + // Log allocation + struct alloc alloc; + void *bt[BACKTRACE_SIZE]; + int bt_len = backtrace(bt, BACKTRACE_SIZE); + char **symbols = backtrace_symbols(bt, bt_len); + + alloc.ptr = ptr; + alloc.size = size; + alloc.backtrace_len = bt_len; + alloc.backtrace = symbols; + + if (allocations_len + 1 > allocations_cap) { + allocations_cap *= 2; + allocations = realloc( + allocations, + sizeof(struct alloc) * allocations_cap + ); + if (!allocations) + ty_log_fatal( + TY_ERR_MEM, + "(%s) (track) ran out of memory", + __func__ + ); + } + + allocations[allocations_len++] = alloc; +#endif // TEENSY_DEBUG + + return ptr; +} + +void *ty_realloc(void *ptr, size_t new_size) +{ + if (new_size == 0) { + ty_free(ptr); + return NULL; + } + + void *new_ptr = realloc(ptr, new_size); + if (!new_ptr) + ty_log_fatal(TY_ERR_MEM, "(%s) ran out of memory", __func__); + +#ifdef TEENSY_DEBUG + for (int i = 0; i < allocations_len; i++) { + struct alloc *alloc = &allocations[i]; + if (alloc->ptr == ptr) { + alloc->ptr = new_ptr; + alloc->size = new_size; + break; + } + } +#endif // TEENSY_DEBUG + + return new_ptr; +} + +void *ty_talloc(size_t size) +{ + void *ptr = ty_alloc(size); + ty_list_append(void*, &temp_allocations, ptr); + return ptr; +} + +void ty_free(void *ptr) +{ + free(ptr); + +#ifdef TEENSY_DEBUG + for (int i = 0; i < allocations_len; i++) { + struct alloc *alloc = &allocations[i]; + if (alloc->ptr == ptr) { + free(alloc->backtrace); + *alloc = allocations[allocations_len - 1]; + allocations_len--; + break; + } + } +#endif // TEENSY_DEBUG +} + +int ty_alloc_count(void) +{ +#ifdef TEENSY_DEBUG + return allocations_len; +#else + return -1; +#endif +} -- cgit v1.3-2-g0d8e