-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfreedom_pool.cpp
executable file
·191 lines (159 loc) · 5.32 KB
/
freedom_pool.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// freedom_pool.cpp v1.37 (C)2023-2024 DEMOS
//
// This is the most efficient block-pool memory management system you can find.
// I tried many before writing my own: rpmalloc, tlsf, many tlsf clones
//
// C and C++ wrappers for malloc/free/new/delete etc
// NEW: v1.31 has been thouroughly tested AGAIN! and it appears to be working well, even with overrides of new/delete/malloc/free
//
// This is the most efficient block-pool memory management system you can find. I tried many before writing my own:
// rpmalloc, tlsf, many tlsf clones.
#include <signal.h>
#include <malloc/malloc.h>
#include "freedom_pool.h"
#define PRINT_V(x) (((x)/MBYTE) > 0) ? (x)/MBYTE : (x)/KBYTE, (((x)/MBYTE) > 0) ? "MB" : "kb"
real_malloc_ptr _Nullable real_malloc = NULL;
real_free_ptr _Nullable real_free = NULL;
real_calloc_ptr _Nullable real_calloc = NULL;
real_realloc_ptr _Nullable real_realloc = NULL;
real_malloc_size_ptr _Nullable real_malloc_size = NULL;
real_malloc_usable_size_ptr _Nullable real_malloc_usable_size = NULL;
static size_t total_alloc = 0L;
static size_t total_max_alloc = 0L;
void reset_freedom_counters() {
total_alloc = 0;
total_max_alloc = 0;
}
FreedomPool<DEFAULT_GROW> bigpool;
#ifndef DISABLE_MALLOC_FREE_OVERRIDE
void *_Nullable malloc(size_t nb_bytes)
{
#ifdef FREEDOM_DEBUG
total_alloc += nb_bytes;
total_max_alloc = F_MAX(total_max_alloc, (size_t)nb_bytes);
if (nb_bytes >= THRESH_DEBUG_PRINT)
DEBUG_PRINTF(stderr, "malloc( %3ld %s ) tot: %3ld %s\n", PRINT_V(nb_bytes), PRINT_V(total_alloc));
#endif
return bigpool.malloc(nb_bytes);
}
void free(void *_Nullable ptr)
{
#ifdef FREEDOM_DEBUG
size_t space = 0;
if (ptr) { space = bigpool.malloc_size(ptr); }
if (space > 0) {
total_alloc -= space;
}
if (space >= THRESH_DEBUG_PRINT)
DEBUG_PRINTF(stderr, " free( %3ld %s ) : spc %3ld %s\n", PRINT_V(space), PRINT_V(total_alloc));
#endif
bigpool.free(ptr);
}
size_t malloc_usable_size(const void *_Nullable ptr)
{
DEBUG_PRINTF(stderr, "malloc_usable_size( %ld )\n", (long)ptr);
return bigpool.malloc_usable_size(ptr);
}
size_t malloc_size(const void *_Nullable ptr)
{
DEBUG_PRINTF(stderr, "malloc_size( %ld )\n", (long)ptr);
return bigpool.malloc_size(ptr);
}
void *_Nullable realloc(void *_Nullable ptr, size_t nb_bytes)
{
#ifdef FREEDOM_DEBUG
// DEBUG_PRINTF(stderr, "realloc( %ld, %ld )\n", (long)p, nb_bytes);
size_t space = 0;
if (ptr) { space = bigpool.malloc_size(ptr); }
void *_Nullable ret = NULL;
ret = bigpool.realloc(ptr, nb_bytes);
// don't count freedompool extend
if (ret) {
total_alloc += nb_bytes - space;
}
#ifdef BREAK_ON_THRESH
if (nb_bytes >= THRESH_DEBUG_BREAK)
DEBUGGER
#endif
total_max_alloc = std::max(total_max_alloc, total_alloc);
if (nb_bytes >= THRESH_DEBUG_PRINT)
DEBUG_PRINTF(stderr, "realloc( %3ld %s ) tot: %3ld %s\n", PRINT_V(nb_bytes), PRINT_V(total_alloc));
return ret;
#endif
return bigpool.realloc(ptr, nb_bytes);
}
void *_Nullable calloc(size_t count, size_t size)
{
#ifdef FREEDOM_DEBUG
// DEBUG_PRINTF(stderr, "calloc( %ld, %ld )\n", (long)count, size);
size_t nb_bytes = size * count;
total_alloc += nb_bytes;
total_max_alloc = std::max(total_max_alloc, total_alloc);
#ifdef BREAK_ON_THRESH
if (nb_bytes >= THRESH_DEBUG_BREAK)
DEBUGGER
#endif
if (nb_bytes >= THRESH_DEBUG_PRINT)
DEBUG_PRINTF(stderr, "calloc( %3ld %s ) tot: %3ld %s\n", PRINT_V(nb_bytes), PRINT_V(total_alloc));
#endif
return bigpool.calloc(count, size);
}
#endif // DISABLE_MALLOC_FREE_OVERRIDE
#ifndef DISABLE_NEWDELETE_OVERRIDE
#ifdef __cplusplus
void * operator new(std::size_t nb_bytes)
{
void *ptr = bigpool.malloc(nb_bytes);
#ifdef FREEDOM_DEBUG
total_alloc += nb_bytes;
#ifdef BREAK_ON_THRESH
if (n >= THRESH_DEBUG_BREAK)
DEBUGGER
#endif
total_max_alloc = std::max(total_max_alloc, total_alloc);
if (nb_bytes >= THRESH_DEBUG_PRINT)
DEBUG_PRINTF(stderr, "new( %3lld %s %7x ) tot: %3ld %s\n", PRINT_V(nb_bytes), ptr, PRINT_V(total_alloc));
#endif
return ptr;
}
void operator delete(void *_Nullable ptr) throw()
{
#ifdef FREEDOM_DEBUG
size_t space = 0;
if (ptr) { space = bigpool.malloc_size(ptr); }
if (space > 0)
total_alloc -= space;
if (space >= THRESH_DEBUG_BREAK)
DEBUG_PRINTF(stderr, "delete ( %3lld %s %7x) : spc %3ld %s\n", PRINT_V(space), ptr, PRINT_V(total_alloc));
#endif
bigpool.free(ptr);
}
void *operator new[](std::size_t nb_bytes)
{
void *ptr = bigpool.malloc(nb_bytes);
#ifdef FREEDOM_DEBUG
total_alloc += nb_bytes;
total_max_alloc = std::max(total_max_alloc, total_alloc);
if (nb_bytes >= THRESH_DEBUG_PRINT)
DEBUG_PRINTF(stderr, "new[]( %3ld %s %7x ) tot: %3ld %s\n", PRINT_V(nb_bytes), ptr, PRINT_V(total_alloc));
#ifdef BREAK_ON_THRESH
if (n >= THRESH_DEBUG_BREAK)
DEBUGGER
#endif
#endif
return ptr;
}
void operator delete[](void *ptr) throw()
{
#ifdef FREEDOM_DEBUG
size_t space = 0;
if (ptr) { space = bigpool.malloc_size(ptr); }
if (space > 0)
total_alloc -= space;
if (space >= THRESH_DEBUG_BREAK)
DEBUG_PRINTF(stderr, "delete[] ( %3ld %s %7x ) : spc %3ld %s\n", PRINT_V(space), ptr, PRINT_V(total_alloc));
#endif
bigpool.free(ptr);
}
#endif
#endif