27
27
* - _aligned_offset_recalloc()
28
28
*/
29
29
30
+ #ifndef _WIN32
31
+ #define _GNU_SOURCE
32
+ #include <dlfcn.h>
33
+ #undef _GNU_SOURCE
34
+ #endif /* _WIN32 */
35
+
30
36
#if (defined PROXY_LIB_USES_JEMALLOC_POOL )
31
37
#include <umf/pools/pool_jemalloc.h>
32
38
#define umfPoolManagerOps umfJemallocPoolOps
@@ -103,38 +109,112 @@ static umf_memory_pool_handle_t Proxy_pool = NULL;
103
109
// it protects us from recursion in umfPool*()
104
110
static __TLS int was_called_from_umfPool = 0 ;
105
111
112
+ typedef void * (* system_aligned_alloc_t )(size_t alignment , size_t size );
113
+ typedef void * (* system_calloc_t )(size_t nmemb , size_t size );
114
+ typedef void (* system_free_t )(void * ptr );
115
+ typedef void * (* system_malloc_t )(size_t size );
116
+ typedef size_t (* system_malloc_usable_size_t )(void * ptr );
117
+ typedef void * (* system_realloc_t )(void * ptr , size_t size );
118
+
119
+ static system_aligned_alloc_t system_aligned_alloc ;
120
+ static system_calloc_t system_calloc ;
121
+ static system_free_t system_free ;
122
+ static system_malloc_t system_malloc ;
123
+ static system_malloc_usable_size_t system_malloc_usable_size ;
124
+ static system_realloc_t system_realloc ;
125
+ static size_t threshold_value = 0 ;
126
+
106
127
/*****************************************************************************/
107
128
/*** The constructor and destructor of the proxy library *********************/
108
129
/*****************************************************************************/
109
130
131
+ #ifndef _WIN32
132
+ static size_t get_size_threshold (void ) {
133
+ char * str_threshold = utils_env_var_get_str ("UMF_PROXY" , "size.threshold=" );
134
+ if (!str_threshold ) {
135
+ return 0 ;
136
+ }
137
+
138
+ // move to the beginning of the number
139
+ str_threshold += strlen ("size.threshold=" );
140
+ // find ';' at the end
141
+ char * end = strstr (str_threshold , ";" );
142
+ if (end ) {
143
+ // replace ';' with '\0' to mark end of the string
144
+ * end = '\0' ;
145
+ }
146
+
147
+ size_t int_threshold = (size_t )atoi (str_threshold );
148
+ LOG_DEBUG ("threshold_value = (char *) %s, (int) %zu" , str_threshold ,
149
+ int_threshold );
150
+
151
+ return int_threshold ;
152
+ }
153
+
154
+ static int dlsym_system_allocator (void ) {
155
+ * ((void * * )(& system_aligned_alloc )) = dlsym (RTLD_NEXT , "aligned_alloc" );
156
+ * ((void * * )(& system_calloc )) = dlsym (RTLD_NEXT , "calloc" );
157
+ * ((void * * )(& system_free )) = dlsym (RTLD_NEXT , "free" );
158
+ * ((void * * )(& system_malloc )) = dlsym (RTLD_NEXT , "malloc" );
159
+ * ((void * * )(& system_malloc_usable_size )) =
160
+ dlsym (RTLD_NEXT , "malloc_usable_size" );
161
+ * ((void * * )(& system_realloc )) = dlsym (RTLD_NEXT , "realloc" );
162
+
163
+ if (system_aligned_alloc && system_calloc && system_free && system_malloc &&
164
+ system_malloc_usable_size && system_realloc ) {
165
+ return 0 ;
166
+ }
167
+
168
+ * ((void * * )(& system_aligned_alloc )) = NULL ;
169
+ * ((void * * )(& system_calloc )) = NULL ;
170
+ * ((void * * )(& system_free )) = NULL ;
171
+ * ((void * * )(& system_malloc )) = NULL ;
172
+ * ((void * * )(& system_malloc_usable_size )) = NULL ;
173
+ * ((void * * )(& system_realloc )) = NULL ;
174
+
175
+ return -1 ;
176
+ }
177
+ #endif /* _WIN32 */
178
+
110
179
void proxy_lib_create_common (void ) {
111
180
utils_log_init ();
112
181
umf_os_memory_provider_params_t os_params =
113
182
umfOsMemoryProviderParamsDefault ();
114
183
umf_result_t umf_result ;
115
184
116
185
#ifndef _WIN32
117
- char shm_name [NAME_MAX ];
186
+ size_t _threshold = get_size_threshold ();
187
+ if (_threshold > 0 ) {
188
+ if (dlsym_system_allocator ()) {
189
+ LOG_ERR ("initialization of the system allocator failed!" );
190
+ exit (-1 );
191
+ }
192
+
193
+ threshold_value = _threshold ;
194
+ LOG_INFO ("system allocator initialized, size threshold value = %zu" ,
195
+ threshold_value );
196
+ }
118
197
119
198
if (utils_env_var_has_str ("UMF_PROXY" , "page.disposition=shared-fd" )) {
120
- LOG_DEBUG ("proxy_lib: using the MAP_SHARED visibility mode with the "
121
- "file descriptor duplication" );
199
+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
200
+ "file descriptor duplication" );
122
201
os_params .visibility = UMF_MEM_MAP_SHARED ;
123
202
os_params .shm_name = NULL ;
124
203
125
204
} else if (utils_env_var_has_str ("UMF_PROXY" ,
126
205
"page.disposition=shared-shm" )) {
127
206
os_params .visibility = UMF_MEM_MAP_SHARED ;
128
207
208
+ char shm_name [NAME_MAX ];
129
209
memset (shm_name , 0 , NAME_MAX );
130
210
sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131
211
os_params .shm_name = shm_name ;
132
212
133
- LOG_DEBUG ("proxy_lib: using the MAP_SHARED visibility mode with the "
134
- "named shared memory: %s" ,
135
- os_params .shm_name );
213
+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
214
+ "named shared memory: %s" ,
215
+ os_params .shm_name );
136
216
}
137
- #endif
217
+ #endif /* _WIN32 */
138
218
139
219
umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140
220
& OS_memory_provider );
@@ -149,16 +229,18 @@ void proxy_lib_create_common(void) {
149
229
LOG_ERR ("creating UMF pool manager failed" );
150
230
exit (-1 );
151
231
}
232
+
152
233
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153
234
// the linear allocator and start using the UMF pool allocator from now on.
235
+ LOG_DEBUG ("proxy library initialized" );
154
236
}
155
237
156
238
void proxy_lib_destroy_common (void ) {
157
239
if (utils_is_running_in_proxy_lib ()) {
158
240
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159
241
// because it could lead to use-after-free in the program's unloader
160
242
// (for example _dl_fini() on Linux).
161
- return ;
243
+ goto fini_proxy_lib_destroy_common ;
162
244
}
163
245
164
246
umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +250,10 @@ void proxy_lib_destroy_common(void) {
168
250
umf_memory_provider_handle_t provider = OS_memory_provider ;
169
251
OS_memory_provider = NULL ;
170
252
umfMemoryProviderDestroy (provider );
253
+ LOG_DEBUG ("proxy library destroyed" );
254
+
255
+ fini_proxy_lib_destroy_common :
256
+ LOG_DEBUG ("proxy library finalized" );
171
257
}
172
258
173
259
/*****************************************************************************/
@@ -246,6 +332,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246
332
/*****************************************************************************/
247
333
248
334
void * malloc (size_t size ) {
335
+ if (size < threshold_value ) {
336
+ return system_malloc (size );
337
+ }
338
+
249
339
if (!was_called_from_umfPool && Proxy_pool ) {
250
340
was_called_from_umfPool = 1 ;
251
341
void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +347,10 @@ void *malloc(size_t size) {
257
347
}
258
348
259
349
void * calloc (size_t nmemb , size_t size ) {
350
+ if ((nmemb * size ) < threshold_value ) {
351
+ return system_calloc (nmemb , size );
352
+ }
353
+
260
354
if (!was_called_from_umfPool && Proxy_pool ) {
261
355
was_called_from_umfPool = 1 ;
262
356
void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +370,20 @@ void free(void *ptr) {
276
370
return ;
277
371
}
278
372
279
- if (Proxy_pool ) {
373
+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280
374
if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281
375
LOG_ERR ("umfPoolFree() failed" );
282
- assert (0 );
283
376
}
284
377
return ;
285
378
}
286
379
287
- assert (0 );
380
+ if (threshold_value ) {
381
+ system_free (ptr );
382
+ return ;
383
+ }
384
+
385
+ LOG_ERR ("free() failed: %p" , ptr );
386
+
288
387
return ;
289
388
}
290
389
@@ -303,18 +402,27 @@ void *realloc(void *ptr, size_t size) {
303
402
return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304
403
}
305
404
306
- if (Proxy_pool ) {
405
+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307
406
was_called_from_umfPool = 1 ;
308
407
void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309
408
was_called_from_umfPool = 0 ;
310
409
return new_ptr ;
311
410
}
312
411
313
- assert (0 );
412
+ if (threshold_value ) {
413
+ return system_realloc (ptr , size );
414
+ }
415
+
416
+ LOG_ERR ("realloc() failed: %p" , ptr );
417
+
314
418
return NULL ;
315
419
}
316
420
317
421
void * aligned_alloc (size_t alignment , size_t size ) {
422
+ if (size < threshold_value ) {
423
+ return system_aligned_alloc (alignment , size );
424
+ }
425
+
318
426
if (!was_called_from_umfPool && Proxy_pool ) {
319
427
was_called_from_umfPool = 1 ;
320
428
void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +438,29 @@ size_t _msize(void *ptr) {
330
438
#else
331
439
size_t malloc_usable_size (void * ptr ) {
332
440
#endif
333
-
334
- // a check to verify we are running the proxy library
441
+ // a check to verify if we are running the proxy library
335
442
if (ptr == (void * )0x01 ) {
336
443
return 0xDEADBEEF ;
337
444
}
338
445
339
- if (!was_called_from_umfPool && Proxy_pool ) {
446
+ if (ba_leak_pool_contains_pointer (ptr )) {
447
+ return 0 ; // unsupported in case of the ba_leak allocator
448
+ }
449
+
450
+ if (!was_called_from_umfPool && Proxy_pool &&
451
+ (umfPoolByPtr (ptr ) == Proxy_pool )) {
340
452
was_called_from_umfPool = 1 ;
341
453
size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342
454
was_called_from_umfPool = 0 ;
343
455
return size ;
344
456
}
345
457
458
+ if (threshold_value ) {
459
+ return system_malloc_usable_size (ptr );
460
+ }
461
+
462
+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
463
+
346
464
return 0 ; // unsupported in this case
347
465
}
348
466
0 commit comments