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
@@ -103,38 +109,112 @@ static umf_memory_pool_handle_t Proxy_pool = NULL;
103109// it protects us from recursion in umfPool*()
104110static __TLS int was_called_from_umfPool = 0 ;
105111
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+
106127/*****************************************************************************/
107128/*** The constructor and destructor of the proxy library *********************/
108129/*****************************************************************************/
109130
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+
110179void proxy_lib_create_common (void ) {
111180 utils_log_init ();
112181 umf_os_memory_provider_params_t os_params =
113182 umfOsMemoryProviderParamsDefault ();
114183 umf_result_t umf_result ;
115184
116185#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+ }
118197
119198 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" );
122201 os_params .visibility = UMF_MEM_MAP_SHARED ;
123202 os_params .shm_name = NULL ;
124203
125204 } else if (utils_env_var_has_str ("UMF_PROXY" ,
126205 "page.disposition=shared-shm" )) {
127206 os_params .visibility = UMF_MEM_MAP_SHARED ;
128207
208+ char shm_name [NAME_MAX ];
129209 memset (shm_name , 0 , NAME_MAX );
130210 sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131211 os_params .shm_name = shm_name ;
132212
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 );
136216 }
137- #endif
217+ #endif /* _WIN32 */
138218
139219 umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140220 & OS_memory_provider );
@@ -149,16 +229,18 @@ void proxy_lib_create_common(void) {
149229 LOG_ERR ("creating UMF pool manager failed" );
150230 exit (-1 );
151231 }
232+
152233 // The UMF pool has just been created (Proxy_pool != NULL). Stop using
153234 // the linear allocator and start using the UMF pool allocator from now on.
235+ LOG_DEBUG ("proxy library initialized" );
154236}
155237
156238void proxy_lib_destroy_common (void ) {
157239 if (utils_is_running_in_proxy_lib ()) {
158240 // We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159241 // because it could lead to use-after-free in the program's unloader
160242 // (for example _dl_fini() on Linux).
161- return ;
243+ goto fini_proxy_lib_destroy_common ;
162244 }
163245
164246 umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +250,10 @@ void proxy_lib_destroy_common(void) {
168250 umf_memory_provider_handle_t provider = OS_memory_provider ;
169251 OS_memory_provider = NULL ;
170252 umfMemoryProviderDestroy (provider );
253+ LOG_DEBUG ("proxy library destroyed" );
254+
255+ fini_proxy_lib_destroy_common :
256+ LOG_DEBUG ("proxy library finalized" );
171257}
172258
173259/*****************************************************************************/
@@ -246,6 +332,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246332/*****************************************************************************/
247333
248334void * malloc (size_t size ) {
335+ if (size < threshold_value ) {
336+ return system_malloc (size );
337+ }
338+
249339 if (!was_called_from_umfPool && Proxy_pool ) {
250340 was_called_from_umfPool = 1 ;
251341 void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +347,10 @@ void *malloc(size_t size) {
257347}
258348
259349void * calloc (size_t nmemb , size_t size ) {
350+ if ((nmemb * size ) < threshold_value ) {
351+ return system_calloc (nmemb , size );
352+ }
353+
260354 if (!was_called_from_umfPool && Proxy_pool ) {
261355 was_called_from_umfPool = 1 ;
262356 void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +370,20 @@ void free(void *ptr) {
276370 return ;
277371 }
278372
279- if (Proxy_pool ) {
373+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280374 if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281375 LOG_ERR ("umfPoolFree() failed" );
282- assert (0 );
283376 }
284377 return ;
285378 }
286379
287- assert (0 );
380+ if (threshold_value ) {
381+ system_free (ptr );
382+ return ;
383+ }
384+
385+ LOG_ERR ("free() failed: %p" , ptr );
386+
288387 return ;
289388}
290389
@@ -303,18 +402,27 @@ void *realloc(void *ptr, size_t size) {
303402 return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304403 }
305404
306- if (Proxy_pool ) {
405+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307406 was_called_from_umfPool = 1 ;
308407 void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309408 was_called_from_umfPool = 0 ;
310409 return new_ptr ;
311410 }
312411
313- assert (0 );
412+ if (threshold_value ) {
413+ return system_realloc (ptr , size );
414+ }
415+
416+ LOG_ERR ("realloc() failed: %p" , ptr );
417+
314418 return NULL ;
315419}
316420
317421void * aligned_alloc (size_t alignment , size_t size ) {
422+ if (size < threshold_value ) {
423+ return system_aligned_alloc (alignment , size );
424+ }
425+
318426 if (!was_called_from_umfPool && Proxy_pool ) {
319427 was_called_from_umfPool = 1 ;
320428 void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +438,29 @@ size_t _msize(void *ptr) {
330438#else
331439size_t malloc_usable_size (void * ptr ) {
332440#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
335442 if (ptr == (void * )0x01 ) {
336443 return 0xDEADBEEF ;
337444 }
338445
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 )) {
340452 was_called_from_umfPool = 1 ;
341453 size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342454 was_called_from_umfPool = 0 ;
343455 return size ;
344456 }
345457
458+ if (threshold_value ) {
459+ return system_malloc_usable_size (ptr );
460+ }
461+
462+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
463+
346464 return 0 ; // unsupported in this case
347465}
348466
0 commit comments