34
34
35
35
/*
36
36
* The UMF proxy library uses three memory allocators:
37
- * 1) the internal linear base allocator (LBA) based on the anonymous mapped memory
38
- * 2) the system allocator (libc malloc on Linux for example)
37
+ * 1) the first "LEAK" instance of the internal linear base allocator
38
+ * based on the anonymous mapped memory that will NOT be destroyed (with API ba_leak_*()).
39
+ * 2) the second instance of the internal linear base allocator
40
+ * based on the anonymous mapped memory that will be destroyed (with API ba_*()).
39
41
* 3) the main one - UMF pool allocator.
40
42
*
41
43
* Ad 1)
42
- * The internal linear base allocator (LBA) is used from the very beginning
43
- * to the start of the constructor of the proxy library to allocate memory
44
- * for OS specific structures used during loading and starting applications
45
- * (for example _dl_init() and _dl_fini() on Linux storing arrays of all
44
+ * The first "LEAK" instance of the internal linear base allocator is used
45
+ * from the very beginning to the start of the constructor of the proxy library
46
+ * to allocate memory for OS specific structures used during loading and starting
47
+ * applications (for example _dl_init() and _dl_fini() on Linux storing arrays of all
46
48
* constructors and destructors that have to be called). That memory will be leaked
47
49
* on purpose (we believe OS will free it), because we cannot free the memory
48
50
* containing array of destructors that have to be called at the end.
53
55
* - malloc(72704)
54
56
*
55
57
* Ad 2)
56
- * The system allocator is used from the start of the constructor of the proxy library
57
- * to the creation of a UMF pool to allocate memory needed by umfMemoryProviderCreate()
58
- * and umfPoolCreate(). It will be freed by the system allocator.
58
+ * The second instance of the internal linear base allocator is used
59
+ * from the start of the constructor of the proxy library to the creation of a UMF pool
60
+ * to allocate memory needed by umfMemoryProviderCreate() and umfPoolCreate().
61
+ * It is created at the start of the constructor of the proxy library
62
+ * and destroyed at the end of the destructor of the proxy library.
59
63
*
60
64
* Ad 3)
61
65
* The UMF pool allocator (the main one) is used from the creation to the destruction
62
66
* of a UMF pool to allocate memory needed by an application. It should be freed
63
67
* by an application.
64
68
*/
65
69
66
- static UTIL_ONCE_FLAG Base_alloc_initialized = UTIL_ONCE_FLAG_INIT ;
67
- static UTIL_ONCE_FLAG alloc_hooks_are_initialized = UTIL_ONCE_FLAG_INIT ;
70
+ static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT ;
68
71
72
+ static umf_ba_linear_pool_t * Base_alloc_leak = NULL ;
69
73
static umf_ba_linear_pool_t * Base_alloc = NULL ;
70
74
static int Constructors_started = 0 ;
71
75
static umf_memory_provider_handle_t OS_memory_provider = NULL ;
@@ -74,17 +78,17 @@ static umf_memory_pool_handle_t Proxy_pool = NULL;
74
78
// it protects us from recursion in umfPool*()
75
79
static __TLS int was_called_from_umfPool = 0 ;
76
80
77
- malloc_func_t System_malloc_func ;
78
- calloc_func_t System_calloc_func ;
79
- realloc_func_t System_realloc_func ;
80
- free_func_t System_free_func ;
81
- aligned_alloc_func_t System_aligned_alloc_func ;
82
-
83
81
/*****************************************************************************/
84
82
/*** The constructor and destructor of the proxy library *********************/
85
83
/*****************************************************************************/
86
84
85
+ static void ba_create (void );
86
+ static void ba_destroy (void );
87
+
87
88
void proxy_lib_create_common (void ) {
89
+ // create the second instance of linear base allocator
90
+ ba_create ();
91
+
88
92
// The constructors of libraries were started. Stop using the linear base
89
93
// allocator that does not free the memory (we leak it on purpose in order
90
94
// to not free the memory used by _dl_fini() containing a map (array)
@@ -117,41 +121,28 @@ void proxy_lib_destroy_common(void) {
117
121
Proxy_pool = NULL ;
118
122
umfPoolDestroy (pool );
119
123
umfMemoryProviderDestroy (OS_memory_provider );
124
+ ba_destroy ();
120
125
}
121
126
122
127
/*****************************************************************************/
123
- /*** The linear base allocator functions ****************** *******************/
128
+ /*** Generic version of realloc() of linear base allocator *******************/
124
129
/*****************************************************************************/
125
130
126
- static void proxy_lib_ba_init (void ) { Base_alloc = umf_ba_linear_create (0 ); }
127
-
128
- static inline void * ba_malloc (size_t size ) {
129
- util_init_once (& Base_alloc_initialized , proxy_lib_ba_init );
130
- return umf_ba_linear_alloc (Base_alloc , size );
131
- }
132
-
133
- static inline void * ba_calloc (size_t nmemb , size_t size ) {
134
- util_init_once (& Base_alloc_initialized , proxy_lib_ba_init );
135
- // umf_ba_linear_alloc() returns zeroed memory
136
- return umf_ba_linear_alloc (Base_alloc , nmemb * size );
137
- }
138
-
139
- static inline void * ba_realloc (void * ptr , size_t size ) {
140
- util_init_once (& Base_alloc_initialized , proxy_lib_ba_init );
141
-
131
+ static void * ba_generic_realloc (umf_ba_linear_pool_t * pool , void * ptr ,
132
+ size_t size ) {
142
133
if (size == 0 ) {
143
- // it means free(ptr), but this BA does not free the memory
134
+ // it means free(ptr), but linear base allocator does not implement free()
144
135
return NULL ;
145
136
}
146
137
147
138
if (ptr == NULL ) {
148
- return umf_ba_linear_alloc (Base_alloc , size );
139
+ return umf_ba_linear_alloc (pool , size );
149
140
}
150
141
151
- size_t max_size = umf_ba_linear_pool_contains_pointer (Base_alloc , ptr );
142
+ size_t max_size = umf_ba_linear_pool_contains_pointer (pool , ptr );
152
143
assert (max_size > 0 ); // assert that pool contains the pointer
153
144
154
- void * new_ptr = umf_ba_linear_alloc (Base_alloc , size );
145
+ void * new_ptr = umf_ba_linear_alloc (pool , size );
155
146
if (!new_ptr ) {
156
147
return NULL ;
157
148
}
@@ -165,42 +156,70 @@ static inline void *ba_realloc(void *ptr, size_t size) {
165
156
return new_ptr ;
166
157
}
167
158
168
- static inline void * ba_aligned_alloc (size_t alignment , size_t size ) {
169
- util_init_once (& Base_alloc_initialized , proxy_lib_ba_init );
170
- void * ptr = umf_ba_linear_alloc (Base_alloc , size + alignment );
159
+ /*****************************************************************************/
160
+ /*** The LEAK linear base allocator functions ********************************/
161
+ /*****************************************************************************/
162
+
163
+ static void ba_leak_create (void ) { Base_alloc_leak = umf_ba_linear_create (0 ); }
164
+
165
+ // it does not implement destroy(), because it will not free memory at all
166
+
167
+ static inline void * ba_leak_malloc (size_t size ) {
168
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
169
+ return umf_ba_linear_alloc (Base_alloc_leak , size );
170
+ }
171
+
172
+ static inline void * ba_leak_calloc (size_t nmemb , size_t size ) {
173
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
174
+ // umf_ba_linear_alloc() returns zeroed memory
175
+ return umf_ba_linear_alloc (Base_alloc_leak , nmemb * size );
176
+ }
177
+
178
+ static inline void * ba_leak_realloc (void * ptr , size_t size ) {
179
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
180
+ return ba_generic_realloc (Base_alloc_leak , ptr , size );
181
+ }
182
+
183
+ static inline void * ba_leak_aligned_alloc (size_t alignment , size_t size ) {
184
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
185
+ void * ptr = umf_ba_linear_alloc (Base_alloc_leak , size + alignment );
171
186
return (void * )ALIGN_UP ((uintptr_t )ptr , alignment );
172
187
}
173
188
174
189
/*****************************************************************************/
175
- /*** The system allocator functions ************************ ******************/
190
+ /*** The second instance of linear base allocator functions ******************/
176
191
/*****************************************************************************/
177
192
178
- static inline void * system_malloc (size_t size ) {
179
- util_init_once (& alloc_hooks_are_initialized , proxy_lib_system_alloc_init );
180
- return System_malloc_func (size );
193
+ static void ba_create (void ) {
194
+ assert (Base_alloc == NULL );
195
+ Base_alloc = umf_ba_linear_create (0 );
196
+ assert (Base_alloc );
181
197
}
182
198
183
- static inline void * system_calloc (size_t nmemb , size_t size ) {
184
- util_init_once (& alloc_hooks_are_initialized , proxy_lib_system_alloc_init );
185
- return System_calloc_func (nmemb , size );
199
+ static void ba_destroy (void ) {
200
+ if (Base_alloc ) {
201
+ umf_ba_linear_pool_t * pool = Base_alloc ;
202
+ Base_alloc = NULL ;
203
+ umf_ba_linear_destroy (pool );
204
+ }
205
+ }
206
+
207
+ static inline void * ba_malloc (size_t size ) {
208
+ return umf_ba_linear_alloc (Base_alloc , size );
186
209
}
187
210
188
- static inline void * system_realloc ( void * ptr , size_t size ) {
189
- util_init_once ( & alloc_hooks_are_initialized , proxy_lib_system_alloc_init );
190
- return System_realloc_func ( ptr , size );
211
+ static inline void * ba_calloc ( size_t nmemb , size_t size ) {
212
+ // umf_ba_linear_alloc() returns zeroed memory
213
+ return umf_ba_linear_alloc ( Base_alloc , nmemb * size );
191
214
}
192
215
193
- static inline void system_free (void * ptr ) {
194
- util_init_once (& alloc_hooks_are_initialized , proxy_lib_system_alloc_init );
195
- System_free_func (ptr );
216
+ static inline void * ba_realloc (void * ptr , size_t size ) {
217
+ return ba_generic_realloc (Base_alloc , ptr , size );
196
218
}
197
219
198
- static inline void * system_aligned_alloc (size_t alignment , size_t size ) {
199
- util_init_once (& alloc_hooks_are_initialized , proxy_lib_system_alloc_init );
200
- if (!System_aligned_alloc_func ) {
201
- return NULL ; // unsupported
202
- }
203
- return System_aligned_alloc_func (alignment , size );
220
+ static inline void * ba_aligned_alloc (size_t alignment , size_t size ) {
221
+ void * ptr = umf_ba_linear_alloc (Base_alloc , size + alignment );
222
+ return (void * )ALIGN_UP ((uintptr_t )ptr , alignment );
204
223
}
205
224
206
225
/*****************************************************************************/
@@ -216,10 +235,10 @@ void *malloc(size_t size) {
216
235
}
217
236
218
237
if (Constructors_started ) {
219
- return system_malloc (size );
238
+ return ba_malloc (size );
220
239
}
221
240
222
- return ba_malloc (size );
241
+ return ba_leak_malloc (size );
223
242
}
224
243
225
244
void * calloc (size_t nmemb , size_t size ) {
@@ -231,10 +250,10 @@ void *calloc(size_t nmemb, size_t size) {
231
250
}
232
251
233
252
if (Constructors_started ) {
234
- return system_calloc (nmemb , size );
253
+ return ba_calloc (nmemb , size );
235
254
}
236
255
237
- return ba_calloc (nmemb , size );
256
+ return ba_leak_calloc (nmemb , size );
238
257
}
239
258
240
259
void * realloc (void * ptr , size_t size ) {
@@ -246,10 +265,10 @@ void *realloc(void *ptr, size_t size) {
246
265
}
247
266
248
267
if (Constructors_started ) {
249
- return system_realloc (ptr , size );
268
+ return ba_realloc (ptr , size );
250
269
}
251
270
252
- return ba_realloc (ptr , size );
271
+ return ba_leak_realloc (ptr , size );
253
272
}
254
273
255
274
void free (void * ptr ) {
@@ -267,9 +286,8 @@ void free(void *ptr) {
267
286
return ;
268
287
}
269
288
270
- if (Constructors_started ) {
271
- system_free (ptr );
272
- }
289
+ // 1) allocations from the second linear base allocator will be freed by ba_destroy().
290
+ // 2) allocations from the leak linear base allocator will not be freed at all.
273
291
274
292
return ;
275
293
}
@@ -283,10 +301,10 @@ void *aligned_alloc(size_t alignment, size_t size) {
283
301
}
284
302
285
303
if (Constructors_started ) {
286
- return system_aligned_alloc (alignment , size );
304
+ return ba_aligned_alloc (alignment , size );
287
305
}
288
306
289
- return ba_aligned_alloc (alignment , size );
307
+ return ba_leak_aligned_alloc (alignment , size );
290
308
}
291
309
292
310
size_t malloc_usable_size (void * ptr ) {
0 commit comments