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