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 ***************************************/
@@ -95,6 +102,24 @@ void utils_init_once(UTIL_ONCE_FLAG *flag, void (*onceCb)(void));
95102 * by an application.
96103 */
97104
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 void * System_library_handle ;
114+ static system_aligned_alloc_t System_aligned_alloc ;
115+ static system_calloc_t System_calloc ;
116+ static system_free_t System_free ;
117+ static system_malloc_t System_malloc ;
118+ static system_malloc_usable_size_t System_malloc_usable_size ;
119+ static system_realloc_t System_realloc ;
120+
121+ static size_t Size_threshold_value = 0 ;
122+
98123static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT ;
99124static umf_ba_linear_pool_t * Base_alloc_leak = NULL ;
100125static umf_memory_provider_handle_t OS_memory_provider = NULL ;
@@ -107,34 +132,123 @@ static __TLS int was_called_from_umfPool = 0;
107132/*** The constructor and destructor of the proxy library *********************/
108133/*****************************************************************************/
109134
135+ // atoi() is defined in stdlib.h, but we cannot include it on Windows
136+ static size_t custom_atoi (const char * str ) {
137+ int len = strlen (str );
138+ int i ;
139+
140+ size_t result = 0 ;
141+
142+ for (i = len - 1 ; i >= 0 ; i -- ) {
143+ if (str [i ] < '0' || str [i ] > '9' ) {
144+ LOG_ERR ("proxy_lib_create_common: size threshold is not a valid "
145+ "number: %s" ,
146+ str );
147+ return 0 ;
148+ }
149+
150+ result = 10 * result + (size_t )(str [i ] - '0' );
151+ }
152+
153+ return result ;
154+ }
155+
156+ static size_t get_size_threshold (void ) {
157+ char * str_threshold = utils_env_var_get_str ("UMF_PROXY" , "size.threshold=" );
158+ if (!str_threshold ) {
159+ return 0 ;
160+ }
161+
162+ // move to the beginning of the number
163+ str_threshold += strlen ("size.threshold=" );
164+ // find ';' at the end
165+ char * end = strstr (str_threshold , ";" );
166+ if (end ) {
167+ // replace ';' with '\0' to mark end of the string
168+ * end = '\0' ;
169+ }
170+
171+ size_t int_threshold = (size_t )custom_atoi (str_threshold );
172+ LOG_DEBUG ("Size_threshold_value = (char *) %s, (int) %zu" , str_threshold ,
173+ int_threshold );
174+
175+ return int_threshold ;
176+ }
177+
178+ static int get_system_allocator_symbols (void ) {
179+ #ifdef _WIN32
180+ System_library_handle = utils_open_library ("msvcrt.dll" , 0 );
181+ #else
182+ System_library_handle = RTLD_NEXT ;
183+ #endif /* _WIN32 */
184+
185+ * ((void * * )(& System_aligned_alloc )) =
186+ utils_get_symbol_addr (System_library_handle , "aligned_alloc" , NULL );
187+ * ((void * * )(& System_calloc )) =
188+ utils_get_symbol_addr (System_library_handle , "calloc" , NULL );
189+ * ((void * * )(& System_free )) =
190+ utils_get_symbol_addr (System_library_handle , "free" , NULL );
191+ * ((void * * )(& System_malloc )) =
192+ utils_get_symbol_addr (System_library_handle , "malloc" , NULL );
193+ * ((void * * )(& System_malloc_usable_size )) = utils_get_symbol_addr (
194+ System_library_handle , "malloc_usable_size" , NULL );
195+ * ((void * * )(& System_realloc )) =
196+ utils_get_symbol_addr (System_library_handle , "realloc" , NULL );
197+
198+ if (System_aligned_alloc && System_calloc && System_free && System_malloc &&
199+ System_malloc_usable_size && System_realloc ) {
200+ return 0 ;
201+ }
202+
203+ * ((void * * )(& System_aligned_alloc )) = NULL ;
204+ * ((void * * )(& System_calloc )) = NULL ;
205+ * ((void * * )(& System_free )) = NULL ;
206+ * ((void * * )(& System_malloc )) = NULL ;
207+ * ((void * * )(& System_malloc_usable_size )) = NULL ;
208+ * ((void * * )(& System_realloc )) = NULL ;
209+
210+ return -1 ;
211+ }
212+
110213void proxy_lib_create_common (void ) {
111214 utils_log_init ();
112215 umf_os_memory_provider_params_t os_params =
113216 umfOsMemoryProviderParamsDefault ();
114217 umf_result_t umf_result ;
115218
116- #ifndef _WIN32
117- char shm_name [NAME_MAX ];
219+ size_t _threshold = get_size_threshold ();
220+ if (_threshold > 0 ) {
221+ if (get_system_allocator_symbols ()) {
222+ LOG_ERR ("initialization of the system allocator failed!" );
223+ exit (-1 );
224+ }
225+
226+ Size_threshold_value = _threshold ;
227+ LOG_INFO ("system allocator initialized, size threshold value = %zu" ,
228+ Size_threshold_value );
229+ }
118230
231+ #ifndef _WIN32
119232 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" );
233+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
234+ "file descriptor duplication" );
122235 os_params .visibility = UMF_MEM_MAP_SHARED ;
123236 os_params .shm_name = NULL ;
124237
125238 } else if (utils_env_var_has_str ("UMF_PROXY" ,
126239 "page.disposition=shared-shm" )) {
127240 os_params .visibility = UMF_MEM_MAP_SHARED ;
128241
242+ char shm_name [NAME_MAX ];
129243 memset (shm_name , 0 , NAME_MAX );
130244 sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131245 os_params .shm_name = shm_name ;
132246
133- LOG_DEBUG ("proxy_lib: using the MAP_SHARED visibility mode with the "
134- "named shared memory: %s" ,
135- os_params .shm_name );
247+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
248+ "named shared memory: %s" ,
249+ os_params .shm_name );
136250 }
137- #endif
251+ #endif /* _WIN32 */
138252
139253 umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140254 & OS_memory_provider );
@@ -149,16 +263,18 @@ void proxy_lib_create_common(void) {
149263 LOG_ERR ("creating UMF pool manager failed" );
150264 exit (-1 );
151265 }
266+
152267 // The UMF pool has just been created (Proxy_pool != NULL). Stop using
153268 // the linear allocator and start using the UMF pool allocator from now on.
269+ LOG_DEBUG ("proxy library initialized" );
154270}
155271
156272void proxy_lib_destroy_common (void ) {
157273 if (utils_is_running_in_proxy_lib ()) {
158274 // We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159275 // because it could lead to use-after-free in the program's unloader
160276 // (for example _dl_fini() on Linux).
161- return ;
277+ goto fini_proxy_lib_destroy_common ;
162278 }
163279
164280 umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +284,18 @@ void proxy_lib_destroy_common(void) {
168284 umf_memory_provider_handle_t provider = OS_memory_provider ;
169285 OS_memory_provider = NULL ;
170286 umfMemoryProviderDestroy (provider );
287+
288+ #ifdef _WIN32
289+ if (System_library_handle ) {
290+ utils_close_library (System_library_handle );
291+ System_library_handle = NULL ;
292+ }
293+ #endif /* _WIN32 */
294+
295+ LOG_DEBUG ("proxy library destroyed" );
296+
297+ fini_proxy_lib_destroy_common :
298+ LOG_DEBUG ("proxy library finalized" );
171299}
172300
173301/*****************************************************************************/
@@ -246,6 +374,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246374/*****************************************************************************/
247375
248376void * malloc (size_t size ) {
377+ if (size < Size_threshold_value ) {
378+ return System_malloc (size );
379+ }
380+
249381 if (!was_called_from_umfPool && Proxy_pool ) {
250382 was_called_from_umfPool = 1 ;
251383 void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +389,10 @@ void *malloc(size_t size) {
257389}
258390
259391void * calloc (size_t nmemb , size_t size ) {
392+ if ((nmemb * size ) < Size_threshold_value ) {
393+ return System_calloc (nmemb , size );
394+ }
395+
260396 if (!was_called_from_umfPool && Proxy_pool ) {
261397 was_called_from_umfPool = 1 ;
262398 void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +412,20 @@ void free(void *ptr) {
276412 return ;
277413 }
278414
279- if (Proxy_pool ) {
415+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280416 if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281417 LOG_ERR ("umfPoolFree() failed" );
282- assert (0 );
283418 }
284419 return ;
285420 }
286421
287- assert (0 );
422+ if (Size_threshold_value ) {
423+ System_free (ptr );
424+ return ;
425+ }
426+
427+ LOG_ERR ("free() failed: %p" , ptr );
428+
288429 return ;
289430}
290431
@@ -303,18 +444,27 @@ void *realloc(void *ptr, size_t size) {
303444 return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304445 }
305446
306- if (Proxy_pool ) {
447+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307448 was_called_from_umfPool = 1 ;
308449 void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309450 was_called_from_umfPool = 0 ;
310451 return new_ptr ;
311452 }
312453
313- assert (0 );
454+ if (Size_threshold_value ) {
455+ return System_realloc (ptr , size );
456+ }
457+
458+ LOG_ERR ("realloc() failed: %p" , ptr );
459+
314460 return NULL ;
315461}
316462
317463void * aligned_alloc (size_t alignment , size_t size ) {
464+ if (size < Size_threshold_value ) {
465+ return System_aligned_alloc (alignment , size );
466+ }
467+
318468 if (!was_called_from_umfPool && Proxy_pool ) {
319469 was_called_from_umfPool = 1 ;
320470 void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +480,28 @@ size_t _msize(void *ptr) {
330480#else
331481size_t malloc_usable_size (void * ptr ) {
332482#endif
333-
334- // a check to verify we are running the proxy library
483+ // a check to verify if we are running the proxy library
335484 if (ptr == (void * )0x01 ) {
336485 return 0xDEADBEEF ;
337486 }
338487
339- if (!was_called_from_umfPool && Proxy_pool ) {
488+ if (ba_leak_pool_contains_pointer (ptr )) {
489+ return 0 ; // unsupported in case of the ba_leak allocator
490+ }
491+
492+ if (Proxy_pool && (umfPoolByPtr (ptr ) == Proxy_pool )) {
340493 was_called_from_umfPool = 1 ;
341494 size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342495 was_called_from_umfPool = 0 ;
343496 return size ;
344497 }
345498
499+ if (Size_threshold_value ) {
500+ return System_malloc_usable_size (ptr );
501+ }
502+
503+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
504+
346505 return 0 ; // unsupported in this case
347506}
348507
0 commit comments