2727 * - _aligned_offset_recalloc()
2828 */
2929
30+ #ifndef _WIN32
31+ #define _GNU_SOURCE // for RTLD_NEXT
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
4854#include "base_alloc_linear.h"
4955#include "proxy_lib.h"
5056#include "utils_common.h"
57+ #include "utils_load_library.h"
5158#include "utils_log.h"
5259
5360#ifdef _WIN32 /* Windows ***************************************/
@@ -94,6 +101,24 @@ void utils_init_once(UTIL_ONCE_FLAG *flag, void (*onceCb)(void));
94101 * of a UMF pool to allocate memory needed by an application. It should be freed
95102 * by an application.
96103 */
104+ #ifndef _WIN32
105+ typedef void * (* system_aligned_alloc_t )(size_t alignment , size_t size );
106+ typedef void * (* system_calloc_t )(size_t nmemb , size_t size );
107+ typedef void (* system_free_t )(void * ptr );
108+ typedef void * (* system_malloc_t )(size_t size );
109+ typedef size_t (* system_malloc_usable_size_t )(void * ptr );
110+ typedef void * (* system_realloc_t )(void * ptr , size_t size );
111+
112+ // pointers to the default system allocator's API
113+ static system_aligned_alloc_t System_aligned_alloc ;
114+ static system_calloc_t System_calloc ;
115+ static system_free_t System_free ;
116+ static system_malloc_t System_malloc ;
117+ static system_malloc_usable_size_t System_malloc_usable_size ;
118+ static system_realloc_t System_realloc ;
119+
120+ static size_t Size_threshold_value = 0 ;
121+ #endif /* _WIN32 */
97122
98123static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT ;
99124static umf_ba_linear_pool_t * Base_alloc_leak = NULL ;
@@ -107,34 +132,104 @@ static __TLS int was_called_from_umfPool = 0;
107132/*** The constructor and destructor of the proxy library *********************/
108133/*****************************************************************************/
109134
135+ #ifndef _WIN32
136+ static size_t get_size_threshold (void ) {
137+ char * str_threshold = utils_env_var_get_str ("UMF_PROXY" , "size.threshold=" );
138+ if (!str_threshold ) {
139+ return 0 ;
140+ }
141+
142+ // move to the beginning of the number
143+ str_threshold += strlen ("size.threshold=" );
144+ // find ';' at the end
145+ char * end = strstr (str_threshold , ";" );
146+ if (end ) {
147+ // replace ';' with '\0' to mark end of the string
148+ * end = '\0' ;
149+ }
150+
151+ long long_threshold = atol (str_threshold );
152+ if (long_threshold < 0 ) {
153+ LOG_ERR ("size threshold cannot be negative! = (char *) %s, (int) %li" ,
154+ str_threshold , long_threshold );
155+ return 0 ;
156+ }
157+
158+ size_t int_threshold = (size_t )long_threshold ;
159+ LOG_DEBUG ("Size_threshold_value = (char *) %s, (int) %zu" , str_threshold ,
160+ int_threshold );
161+
162+ return int_threshold ;
163+ }
164+
165+ static int get_system_allocator_symbols (void ) {
166+ * ((void * * )(& System_aligned_alloc )) =
167+ utils_get_symbol_addr (RTLD_NEXT , "aligned_alloc" , NULL );
168+ * ((void * * )(& System_calloc )) =
169+ utils_get_symbol_addr (RTLD_NEXT , "calloc" , NULL );
170+ * ((void * * )(& System_free )) = utils_get_symbol_addr (RTLD_NEXT , "free" , NULL );
171+ * ((void * * )(& System_malloc )) =
172+ utils_get_symbol_addr (RTLD_NEXT , "malloc" , NULL );
173+ * ((void * * )(& System_malloc_usable_size )) =
174+ utils_get_symbol_addr (RTLD_NEXT , "malloc_usable_size" , NULL );
175+ * ((void * * )(& System_realloc )) =
176+ utils_get_symbol_addr (RTLD_NEXT , "realloc" , NULL );
177+
178+ if (System_aligned_alloc && System_calloc && System_free && System_malloc &&
179+ System_malloc_usable_size && System_realloc ) {
180+ return 0 ;
181+ }
182+
183+ * ((void * * )(& System_aligned_alloc )) = NULL ;
184+ * ((void * * )(& System_calloc )) = NULL ;
185+ * ((void * * )(& System_free )) = NULL ;
186+ * ((void * * )(& System_malloc )) = NULL ;
187+ * ((void * * )(& System_malloc_usable_size )) = NULL ;
188+ * ((void * * )(& System_realloc )) = NULL ;
189+
190+ return -1 ;
191+ }
192+ #endif /* _WIN32 */
193+
110194void proxy_lib_create_common (void ) {
111195 utils_log_init ();
112196 umf_os_memory_provider_params_t os_params =
113197 umfOsMemoryProviderParamsDefault ();
114198 umf_result_t umf_result ;
115199
116200#ifndef _WIN32
117- char shm_name [NAME_MAX ];
201+ size_t _threshold = get_size_threshold ();
202+ if (_threshold > 0 ) {
203+ if (get_system_allocator_symbols ()) {
204+ LOG_ERR ("initialization of the system allocator failed!" );
205+ exit (-1 );
206+ }
207+
208+ Size_threshold_value = _threshold ;
209+ LOG_INFO ("system allocator initialized, size threshold value = %zu" ,
210+ Size_threshold_value );
211+ }
118212
119213 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" );
214+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
215+ "file descriptor duplication" );
122216 os_params .visibility = UMF_MEM_MAP_SHARED ;
123217 os_params .shm_name = NULL ;
124218
125219 } else if (utils_env_var_has_str ("UMF_PROXY" ,
126220 "page.disposition=shared-shm" )) {
127221 os_params .visibility = UMF_MEM_MAP_SHARED ;
128222
223+ char shm_name [NAME_MAX ];
129224 memset (shm_name , 0 , NAME_MAX );
130225 sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131226 os_params .shm_name = shm_name ;
132227
133- LOG_DEBUG ("proxy_lib: using the MAP_SHARED visibility mode with the "
134- "named shared memory: %s" ,
135- os_params .shm_name );
228+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
229+ "named shared memory: %s" ,
230+ os_params .shm_name );
136231 }
137- #endif
232+ #endif /* _WIN32 */
138233
139234 umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140235 & OS_memory_provider );
@@ -149,16 +244,18 @@ void proxy_lib_create_common(void) {
149244 LOG_ERR ("creating UMF pool manager failed" );
150245 exit (-1 );
151246 }
247+
152248 // The UMF pool has just been created (Proxy_pool != NULL). Stop using
153249 // the linear allocator and start using the UMF pool allocator from now on.
250+ LOG_DEBUG ("proxy library initialized" );
154251}
155252
156253void proxy_lib_destroy_common (void ) {
157254 if (utils_is_running_in_proxy_lib ()) {
158255 // We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159256 // because it could lead to use-after-free in the program's unloader
160257 // (for example _dl_fini() on Linux).
161- return ;
258+ goto fini_proxy_lib_destroy_common ;
162259 }
163260
164261 umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +265,10 @@ void proxy_lib_destroy_common(void) {
168265 umf_memory_provider_handle_t provider = OS_memory_provider ;
169266 OS_memory_provider = NULL ;
170267 umfMemoryProviderDestroy (provider );
268+ LOG_DEBUG ("proxy library destroyed" );
269+
270+ fini_proxy_lib_destroy_common :
271+ LOG_DEBUG ("proxy library finalized" );
171272}
172273
173274/*****************************************************************************/
@@ -246,6 +347,12 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246347/*****************************************************************************/
247348
248349void * malloc (size_t size ) {
350+ #ifndef _WIN32
351+ if (size < Size_threshold_value ) {
352+ return System_malloc (size );
353+ }
354+ #endif /* _WIN32 */
355+
249356 if (!was_called_from_umfPool && Proxy_pool ) {
250357 was_called_from_umfPool = 1 ;
251358 void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +364,12 @@ void *malloc(size_t size) {
257364}
258365
259366void * calloc (size_t nmemb , size_t size ) {
367+ #ifndef _WIN32
368+ if ((nmemb * size ) < Size_threshold_value ) {
369+ return System_calloc (nmemb , size );
370+ }
371+ #endif /* _WIN32 */
372+
260373 if (!was_called_from_umfPool && Proxy_pool ) {
261374 was_called_from_umfPool = 1 ;
262375 void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +389,22 @@ void free(void *ptr) {
276389 return ;
277390 }
278391
279- if (Proxy_pool ) {
392+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280393 if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281394 LOG_ERR ("umfPoolFree() failed" );
282- assert (0 );
283395 }
284396 return ;
285397 }
286398
287- assert (0 );
399+ #ifndef _WIN32
400+ if (Size_threshold_value ) {
401+ System_free (ptr );
402+ return ;
403+ }
404+ #endif /* _WIN32 */
405+
406+ LOG_ERR ("free() failed: %p" , ptr );
407+
288408 return ;
289409}
290410
@@ -303,18 +423,31 @@ void *realloc(void *ptr, size_t size) {
303423 return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304424 }
305425
306- if (Proxy_pool ) {
426+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307427 was_called_from_umfPool = 1 ;
308428 void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309429 was_called_from_umfPool = 0 ;
310430 return new_ptr ;
311431 }
312432
313- assert (0 );
433+ #ifndef _WIN32
434+ if (Size_threshold_value ) {
435+ return System_realloc (ptr , size );
436+ }
437+ #endif /* _WIN32 */
438+
439+ LOG_ERR ("realloc() failed: %p" , ptr );
440+
314441 return NULL ;
315442}
316443
317444void * aligned_alloc (size_t alignment , size_t size ) {
445+ #ifndef _WIN32
446+ if (size < Size_threshold_value ) {
447+ return System_aligned_alloc (alignment , size );
448+ }
449+ #endif /* _WIN32 */
450+
318451 if (!was_called_from_umfPool && Proxy_pool ) {
319452 was_called_from_umfPool = 1 ;
320453 void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +463,30 @@ size_t _msize(void *ptr) {
330463#else
331464size_t malloc_usable_size (void * ptr ) {
332465#endif
333-
334- // a check to verify we are running the proxy library
466+ // a check to verify if we are running the proxy library
335467 if (ptr == (void * )0x01 ) {
336468 return 0xDEADBEEF ;
337469 }
338470
339- if (!was_called_from_umfPool && Proxy_pool ) {
471+ if (ba_leak_pool_contains_pointer (ptr )) {
472+ return 0 ; // unsupported in case of the ba_leak allocator
473+ }
474+
475+ if (Proxy_pool && (umfPoolByPtr (ptr ) == Proxy_pool )) {
340476 was_called_from_umfPool = 1 ;
341477 size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342478 was_called_from_umfPool = 0 ;
343479 return size ;
344480 }
345481
482+ #ifndef _WIN32
483+ if (Size_threshold_value ) {
484+ return System_malloc_usable_size (ptr );
485+ }
486+ #endif /* _WIN32 */
487+
488+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
489+
346490 return 0 ; // unsupported in this case
347491}
348492
0 commit comments