7#if defined(LMMC_BUILD_TESTS) || defined(LMMC_DEBUG_LEAKS)
11#ifdef LMMC_DEBUG_LEAKS
12static void lmmc_debug_leaks_alloc(
void);
13static void lmmc_debug_leaks_free(
void);
16#ifdef LMMC_BUILD_TESTS
17static _Atomic
size_t lmmc_memory_fail_after = SIZE_MAX;
19void lmmc_memory_fail_after_for_test(
size_t successful_allocations) {
20 atomic_store_explicit(
21 &lmmc_memory_fail_after, successful_allocations, memory_order_relaxed);
24static int lmmc_memory_should_fail(
void) {
25 size_t remaining = atomic_load_explicit(
26 &lmmc_memory_fail_after, memory_order_relaxed);
27 while (remaining != SIZE_MAX) {
29 if (atomic_compare_exchange_weak_explicit(
30 &lmmc_memory_fail_after, &remaining, SIZE_MAX,
31 memory_order_relaxed, memory_order_relaxed)) {
34 }
else if (atomic_compare_exchange_weak_explicit(
35 &lmmc_memory_fail_after, &remaining, remaining - 1,
36 memory_order_relaxed, memory_order_relaxed)) {
43static int lmmc_memory_should_fail(
void) {
return 0; }
47 if (lmmc_memory_should_fail())
return NULL;
48 void* pointer = malloc(size);
49#ifdef LMMC_DEBUG_LEAKS
50 if (pointer != NULL) lmmc_debug_leaks_alloc();
57 if (!lmmc_safe_mul_size(count, element_size, &bytes))
return NULL;
62 size_t count,
size_t extra,
size_t element_size) {
64 if (!lmmc_safe_add_size(count, extra, &total))
return NULL;
69 size_t rows,
size_t cols,
size_t element_size) {
71 if (!lmmc_safe_mul_size(rows, cols, &count))
return NULL;
76#ifdef LMMC_DEBUG_LEAKS
77 if (pointer != NULL) lmmc_debug_leaks_free();
85#ifdef LMMC_DEBUG_LEAKS
86 lmmc_debug_leaks_free();
91 if (lmmc_memory_should_fail())
return NULL;
92 return realloc(pointer, size);
95#ifdef LMMC_DEBUG_LEAKS
96static _Atomic
size_t lmmc_debug_allocation_count = 0;
98static void lmmc_debug_leaks_alloc(
void) {
99 atomic_fetch_add_explicit(
100 &lmmc_debug_allocation_count, 1, memory_order_relaxed);
103static void lmmc_debug_leaks_free(
void) {
104 size_t count = atomic_load_explicit(
105 &lmmc_debug_allocation_count, memory_order_relaxed);
106 while (count != 0 && !atomic_compare_exchange_weak_explicit(
107 &lmmc_debug_allocation_count, &count, count - 1,
108 memory_order_relaxed, memory_order_relaxed)) {}
112 const size_t count = atomic_load_explicit(
113 &lmmc_debug_allocation_count, memory_order_relaxed);
114 return count > (size_t)INT64_MAX ? INT64_MAX : count;
long long lmmc_debug_leaks_get_count(void)
Get the number of persistent allocations currently owned by LMMC.
void * lmmc_memory_realloc(void *pointer, size_t size)
void * lmmc_memory_alloc_array(size_t count, size_t element_size)
void * lmmc_memory_alloc(size_t size)
void * lmmc_memory_alloc_array_plus(size_t count, size_t extra, size_t element_size)
void * lmmc_memory_alloc_array_2d(size_t rows, size_t cols, size_t element_size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.