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 ;
@@ -84,7 +88,13 @@ aligned_alloc_func_t System_aligned_alloc_func;
84
88
/*** The constructor and destructor of the proxy library *********************/
85
89
/*****************************************************************************/
86
90
91
+ static void ba_create (void );
92
+ static void ba_destroy (void );
93
+
87
94
void proxy_lib_create_common (void ) {
95
+ // create the second instance of linear base allocator
96
+ ba_create ();
97
+
88
98
// The constructors of libraries were started. Stop using the linear base
89
99
// allocator that does not free the memory (we leak it on purpose in order
90
100
// to not free the memory used by _dl_fini() containing a map (array)
@@ -117,41 +127,28 @@ void proxy_lib_destroy_common(void) {
117
127
Proxy_pool = NULL ;
118
128
umfPoolDestroy (pool );
119
129
umfMemoryProviderDestroy (OS_memory_provider );
130
+ ba_destroy ();
120
131
}
121
132
122
133
/*****************************************************************************/
123
- /*** The linear base allocator functions ****************** *******************/
134
+ /*** Generic version of realloc() of linear base allocator *******************/
124
135
/*****************************************************************************/
125
136
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
-
137
+ static void * ba_generic_realloc (umf_ba_linear_pool_t * pool , void * ptr ,
138
+ size_t size ) {
142
139
if (size == 0 ) {
143
- // it means free(ptr), but this BA does not free the memory
140
+ // it means free(ptr), but linear base allocator does not implement free()
144
141
return NULL ;
145
142
}
146
143
147
144
if (ptr == NULL ) {
148
- return umf_ba_linear_alloc (Base_alloc , size );
145
+ return umf_ba_linear_alloc (pool , size );
149
146
}
150
147
151
- size_t max_size = umf_ba_linear_pool_contains_pointer (Base_alloc , ptr );
148
+ size_t max_size = umf_ba_linear_pool_contains_pointer (pool , ptr );
152
149
assert (max_size > 0 ); // assert that pool contains the pointer
153
150
154
- void * new_ptr = umf_ba_linear_alloc (Base_alloc , size );
151
+ void * new_ptr = umf_ba_linear_alloc (pool , size );
155
152
if (!new_ptr ) {
156
153
return NULL ;
157
154
}
@@ -165,42 +162,70 @@ static inline void *ba_realloc(void *ptr, size_t size) {
165
162
return new_ptr ;
166
163
}
167
164
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 );
165
+ /*****************************************************************************/
166
+ /*** The LEAK linear base allocator functions ********************************/
167
+ /*****************************************************************************/
168
+
169
+ static void ba_leak_create (void ) { Base_alloc_leak = umf_ba_linear_create (0 ); }
170
+
171
+ // it does not implement destroy(), because it will not free memory at all
172
+
173
+ static inline void * ba_leak_malloc (size_t size ) {
174
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
175
+ return umf_ba_linear_alloc (Base_alloc_leak , size );
176
+ }
177
+
178
+ static inline void * ba_leak_calloc (size_t nmemb , size_t size ) {
179
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
180
+ // umf_ba_linear_alloc() returns zeroed memory
181
+ return umf_ba_linear_alloc (Base_alloc_leak , nmemb * size );
182
+ }
183
+
184
+ static inline void * ba_leak_realloc (void * ptr , size_t size ) {
185
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
186
+ return ba_generic_realloc (Base_alloc_leak , ptr , size );
187
+ }
188
+
189
+ static inline void * ba_leak_aligned_alloc (size_t alignment , size_t size ) {
190
+ util_init_once (& Base_alloc_leak_initialized , ba_leak_create );
191
+ void * ptr = umf_ba_linear_alloc (Base_alloc_leak , size + alignment );
171
192
return (void * )ALIGN_UP ((uintptr_t )ptr , alignment );
172
193
}
173
194
174
195
/*****************************************************************************/
175
- /*** The system allocator functions ************************ ******************/
196
+ /*** The second instance of linear base allocator functions ******************/
176
197
/*****************************************************************************/
177
198
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 );
199
+ static void ba_create (void ) {
200
+ assert (Base_alloc == NULL );
201
+ Base_alloc = umf_ba_linear_create (0 );
202
+ assert (Base_alloc );
181
203
}
182
204
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 );
205
+ static void ba_destroy (void ) {
206
+ if (Base_alloc ) {
207
+ umf_ba_linear_pool_t * pool = Base_alloc ;
208
+ Base_alloc = NULL ;
209
+ umf_ba_linear_destroy (pool );
210
+ }
186
211
}
187
212
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 );
213
+ static inline void * ba_malloc (size_t size ) {
214
+ return umf_ba_linear_alloc (Base_alloc , size );
191
215
}
192
216
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 );
217
+ static inline void * ba_calloc ( size_t nmemb , size_t size ) {
218
+ // umf_ba_linear_alloc() returns zeroed memory
219
+ return umf_ba_linear_alloc ( Base_alloc , nmemb * size );
196
220
}
197
221
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 );
222
+ static inline void * ba_realloc (void * ptr , size_t size ) {
223
+ return ba_generic_realloc (Base_alloc , ptr , size );
224
+ }
225
+
226
+ static inline void * ba_aligned_alloc (size_t alignment , size_t size ) {
227
+ void * ptr = umf_ba_linear_alloc (Base_alloc , size + alignment );
228
+ return (void * )ALIGN_UP ((uintptr_t )ptr , alignment );
204
229
}
205
230
206
231
/*****************************************************************************/
@@ -216,10 +241,10 @@ void *malloc(size_t size) {
216
241
}
217
242
218
243
if (Constructors_started ) {
219
- return system_malloc (size );
244
+ return ba_malloc (size );
220
245
}
221
246
222
- return ba_malloc (size );
247
+ return ba_leak_malloc (size );
223
248
}
224
249
225
250
void * calloc (size_t nmemb , size_t size ) {
@@ -231,10 +256,10 @@ void *calloc(size_t nmemb, size_t size) {
231
256
}
232
257
233
258
if (Constructors_started ) {
234
- return system_calloc (nmemb , size );
259
+ return ba_calloc (nmemb , size );
235
260
}
236
261
237
- return ba_calloc (nmemb , size );
262
+ return ba_leak_calloc (nmemb , size );
238
263
}
239
264
240
265
void * realloc (void * ptr , size_t size ) {
@@ -246,10 +271,10 @@ void *realloc(void *ptr, size_t size) {
246
271
}
247
272
248
273
if (Constructors_started ) {
249
- return system_realloc (ptr , size );
274
+ return ba_realloc (ptr , size );
250
275
}
251
276
252
- return ba_realloc (ptr , size );
277
+ return ba_leak_realloc (ptr , size );
253
278
}
254
279
255
280
void free (void * ptr ) {
@@ -267,9 +292,8 @@ void free(void *ptr) {
267
292
return ;
268
293
}
269
294
270
- if (Constructors_started ) {
271
- system_free (ptr );
272
- }
295
+ // 1) allocations from the second linear base allocator will be freed by ba_destroy().
296
+ // 2) allocations from the leak linear base allocator will not be freed at all.
273
297
274
298
return ;
275
299
}
@@ -283,10 +307,10 @@ void *aligned_alloc(size_t alignment, size_t size) {
283
307
}
284
308
285
309
if (Constructors_started ) {
286
- return system_aligned_alloc (alignment , size );
310
+ return ba_aligned_alloc (alignment , size );
287
311
}
288
312
289
- return ba_aligned_alloc (alignment , size );
313
+ return ba_leak_aligned_alloc (alignment , size );
290
314
}
291
315
292
316
size_t malloc_usable_size (void * ptr ) {
0 commit comments