LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
memory_bridge.c
浏览该文件的文档.
1#include "memory_bridge.h"
2#include "internal.h"
3
4#include <stdint.h>
5#include <stdlib.h>
6
7#if defined(LMMC_BUILD_TESTS) || defined(LMMC_DEBUG_LEAKS)
8#include <stdatomic.h>
9#endif
10
11#ifdef LMMC_DEBUG_LEAKS
12static void lmmc_debug_leaks_alloc(void);
13static void lmmc_debug_leaks_free(void);
14#endif
15
16#ifdef LMMC_BUILD_TESTS
17static _Atomic size_t lmmc_memory_fail_after = SIZE_MAX;
18
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);
22}
23
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) {
28 if (remaining == 0) {
29 if (atomic_compare_exchange_weak_explicit(
30 &lmmc_memory_fail_after, &remaining, SIZE_MAX,
31 memory_order_relaxed, memory_order_relaxed)) {
32 return 1;
33 }
34 } else if (atomic_compare_exchange_weak_explicit(
35 &lmmc_memory_fail_after, &remaining, remaining - 1,
36 memory_order_relaxed, memory_order_relaxed)) {
37 return 0;
38 }
39 }
40 return 0;
41}
42#else
43static int lmmc_memory_should_fail(void) { return 0; }
44#endif
45
46void* lmmc_memory_alloc(size_t size) {
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();
51#endif
52 return pointer;
53}
54
55void* lmmc_memory_alloc_array(size_t count, size_t element_size) {
56 size_t bytes = 0;
57 if (!lmmc_safe_mul_size(count, element_size, &bytes)) return NULL;
58 return lmmc_memory_alloc(bytes);
59}
60
62 size_t count, size_t extra, size_t element_size) {
63 size_t total = 0;
64 if (!lmmc_safe_add_size(count, extra, &total)) return NULL;
65 return lmmc_memory_alloc_array(total, element_size);
66}
67
69 size_t rows, size_t cols, size_t element_size) {
70 size_t count = 0;
71 if (!lmmc_safe_mul_size(rows, cols, &count)) return NULL;
72 return lmmc_memory_alloc_array(count, element_size);
73}
74
75void lmmc_memory_free(void* pointer) {
76#ifdef LMMC_DEBUG_LEAKS
77 if (pointer != NULL) lmmc_debug_leaks_free();
78#endif
79 free(pointer);
80}
81
82void* lmmc_memory_realloc(void* pointer, size_t size) {
83 if (pointer == NULL) return lmmc_memory_alloc(size);
84 if (size == 0) {
85#ifdef LMMC_DEBUG_LEAKS
86 lmmc_debug_leaks_free();
87#endif
88 free(pointer);
89 return NULL;
90 }
91 if (lmmc_memory_should_fail()) return NULL;
92 return realloc(pointer, size);
93}
94
95#ifdef LMMC_DEBUG_LEAKS
96static _Atomic size_t lmmc_debug_allocation_count = 0;
97
98static void lmmc_debug_leaks_alloc(void) {
99 atomic_fetch_add_explicit(
100 &lmmc_debug_allocation_count, 1, memory_order_relaxed);
101}
102
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)) {}
109}
110
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;
115}
116#endif
long long lmmc_debug_leaks_get_count(void)
Get the number of persistent allocations currently owned by LMMC.
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.