2727 * - _aligned_offset_recalloc()
2828 */
2929
30+ #ifndef _WIN32
31+ #define _GNU_SOURCE
32+ #include <dlfcn.h>
33+ #undef _GNU_SOURCE
34+ #endif /* _WIN32 */
35+
3036#if (defined PROXY_LIB_USES_JEMALLOC_POOL )
3137#include <umf/pools/pool_jemalloc.h>
3238#define umfPoolManagerOps umfJemallocPoolOps
@@ -95,6 +101,23 @@ void utils_init_once(UTIL_ONCE_FLAG *flag, void (*onceCb)(void));
95101 * by an application.
96102 */
97103
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+
98121static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT ;
99122static umf_ba_linear_pool_t * Base_alloc_leak = NULL ;
100123static umf_memory_provider_handle_t OS_memory_provider = NULL ;
@@ -107,34 +130,93 @@ static __TLS int was_called_from_umfPool = 0;
107130/*** The constructor and destructor of the proxy library *********************/
108131/*****************************************************************************/
109132
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+
110181void proxy_lib_create_common (void ) {
111182 utils_log_init ();
112183 umf_os_memory_provider_params_t os_params =
113184 umfOsMemoryProviderParamsDefault ();
114185 umf_result_t umf_result ;
115186
116187#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+ }
118199
119200 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" );
122203 os_params .visibility = UMF_MEM_MAP_SHARED ;
123204 os_params .shm_name = NULL ;
124205
125206 } else if (utils_env_var_has_str ("UMF_PROXY" ,
126207 "page.disposition=shared-shm" )) {
127208 os_params .visibility = UMF_MEM_MAP_SHARED ;
128209
210+ char shm_name [NAME_MAX ];
129211 memset (shm_name , 0 , NAME_MAX );
130212 sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131213 os_params .shm_name = shm_name ;
132214
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 );
136218 }
137- #endif
219+ #endif /* _WIN32 */
138220
139221 umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140222 & OS_memory_provider );
@@ -149,16 +231,18 @@ void proxy_lib_create_common(void) {
149231 LOG_ERR ("creating UMF pool manager failed" );
150232 exit (-1 );
151233 }
234+
152235 // The UMF pool has just been created (Proxy_pool != NULL). Stop using
153236 // the linear allocator and start using the UMF pool allocator from now on.
237+ LOG_DEBUG ("proxy library initialized" );
154238}
155239
156240void proxy_lib_destroy_common (void ) {
157241 if (utils_is_running_in_proxy_lib ()) {
158242 // We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159243 // because it could lead to use-after-free in the program's unloader
160244 // (for example _dl_fini() on Linux).
161- return ;
245+ goto fini_proxy_lib_destroy_common ;
162246 }
163247
164248 umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +252,10 @@ void proxy_lib_destroy_common(void) {
168252 umf_memory_provider_handle_t provider = OS_memory_provider ;
169253 OS_memory_provider = NULL ;
170254 umfMemoryProviderDestroy (provider );
255+ LOG_DEBUG ("proxy library destroyed" );
256+
257+ fini_proxy_lib_destroy_common :
258+ LOG_DEBUG ("proxy library finalized" );
171259}
172260
173261/*****************************************************************************/
@@ -246,6 +334,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246334/*****************************************************************************/
247335
248336void * malloc (size_t size ) {
337+ if (size < Size_threshold_value ) {
338+ return System_malloc (size );
339+ }
340+
249341 if (!was_called_from_umfPool && Proxy_pool ) {
250342 was_called_from_umfPool = 1 ;
251343 void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +349,10 @@ void *malloc(size_t size) {
257349}
258350
259351void * calloc (size_t nmemb , size_t size ) {
352+ if ((nmemb * size ) < Size_threshold_value ) {
353+ return System_calloc (nmemb , size );
354+ }
355+
260356 if (!was_called_from_umfPool && Proxy_pool ) {
261357 was_called_from_umfPool = 1 ;
262358 void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +372,20 @@ void free(void *ptr) {
276372 return ;
277373 }
278374
279- if (Proxy_pool ) {
375+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280376 if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281377 LOG_ERR ("umfPoolFree() failed" );
282- assert (0 );
283378 }
284379 return ;
285380 }
286381
287- assert (0 );
382+ if (Size_threshold_value ) {
383+ System_free (ptr );
384+ return ;
385+ }
386+
387+ LOG_ERR ("free() failed: %p" , ptr );
388+
288389 return ;
289390}
290391
@@ -303,18 +404,27 @@ void *realloc(void *ptr, size_t size) {
303404 return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304405 }
305406
306- if (Proxy_pool ) {
407+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307408 was_called_from_umfPool = 1 ;
308409 void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309410 was_called_from_umfPool = 0 ;
310411 return new_ptr ;
311412 }
312413
313- assert (0 );
414+ if (Size_threshold_value ) {
415+ return System_realloc (ptr , size );
416+ }
417+
418+ LOG_ERR ("realloc() failed: %p" , ptr );
419+
314420 return NULL ;
315421}
316422
317423void * aligned_alloc (size_t alignment , size_t size ) {
424+ if (size < Size_threshold_value ) {
425+ return System_aligned_alloc (alignment , size );
426+ }
427+
318428 if (!was_called_from_umfPool && Proxy_pool ) {
319429 was_called_from_umfPool = 1 ;
320430 void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +440,29 @@ size_t _msize(void *ptr) {
330440#else
331441size_t malloc_usable_size (void * ptr ) {
332442#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
335444 if (ptr == (void * )0x01 ) {
336445 return 0xDEADBEEF ;
337446 }
338447
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 )) {
340454 was_called_from_umfPool = 1 ;
341455 size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342456 was_called_from_umfPool = 0 ;
343457 return size ;
344458 }
345459
460+ if (Size_threshold_value ) {
461+ return System_malloc_usable_size (ptr );
462+ }
463+
464+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
465+
346466 return 0 ; // unsupported in this case
347467}
348468
0 commit comments