27
27
* - _aligned_offset_recalloc()
28
28
*/
29
29
30
+ #ifndef _WIN32
31
+ #define _GNU_SOURCE // for RTLD_NEXT
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
48
54
#include "base_alloc_linear.h"
49
55
#include "proxy_lib.h"
50
56
#include "utils_common.h"
57
+ #include "utils_load_library.h"
51
58
#include "utils_log.h"
52
59
53
60
#ifdef _WIN32 /* Windows ***************************************/
@@ -95,6 +102,24 @@ void utils_init_once(UTIL_ONCE_FLAG *flag, void (*onceCb)(void));
95
102
* by an application.
96
103
*/
97
104
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
+
98
123
static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT ;
99
124
static umf_ba_linear_pool_t * Base_alloc_leak = NULL ;
100
125
static umf_memory_provider_handle_t OS_memory_provider = NULL ;
@@ -107,34 +132,120 @@ static __TLS int was_called_from_umfPool = 0;
107
132
/*** The constructor and destructor of the proxy library *********************/
108
133
/*****************************************************************************/
109
134
135
+ // atoi() is defined in stdlib.h, but we cannot include it on Windows
136
+ static size_t custom_atoi (const char * str ) {
137
+ size_t result = 0 ;
138
+
139
+ for (int i = 0 ; str [i ]; i ++ ) {
140
+ if (str [i ] < '0' || str [i ] > '9' ) {
141
+ LOG_ERR ("proxy_lib_create_common: size threshold is not a valid "
142
+ "number: %s" ,
143
+ str );
144
+ return 0 ;
145
+ }
146
+
147
+ result = 10 * result + (size_t )(str [i ] - '0' );
148
+ }
149
+
150
+ return result ;
151
+ }
152
+
153
+ static size_t get_size_threshold (void ) {
154
+ char * str_threshold = utils_env_var_get_str ("UMF_PROXY" , "size.threshold=" );
155
+ if (!str_threshold ) {
156
+ return 0 ;
157
+ }
158
+
159
+ // move to the beginning of the number
160
+ str_threshold += strlen ("size.threshold=" );
161
+ // find ';' at the end
162
+ char * end = strstr (str_threshold , ";" );
163
+ if (end ) {
164
+ // replace ';' with '\0' to mark end of the string
165
+ * end = '\0' ;
166
+ }
167
+
168
+ size_t int_threshold = (size_t )custom_atoi (str_threshold );
169
+ LOG_DEBUG ("Size_threshold_value = (char *) %s, (int) %zu" , str_threshold ,
170
+ int_threshold );
171
+
172
+ return int_threshold ;
173
+ }
174
+
175
+ static int get_system_allocator_symbols (void ) {
176
+ #ifdef _WIN32
177
+ System_library_handle = utils_open_library ("msvcrt.dll" , 0 );
178
+ #else
179
+ System_library_handle = RTLD_NEXT ;
180
+ #endif /* _WIN32 */
181
+
182
+ * ((void * * )(& System_aligned_alloc )) =
183
+ utils_get_symbol_addr (System_library_handle , "aligned_alloc" , NULL );
184
+ * ((void * * )(& System_calloc )) =
185
+ utils_get_symbol_addr (System_library_handle , "calloc" , NULL );
186
+ * ((void * * )(& System_free )) =
187
+ utils_get_symbol_addr (System_library_handle , "free" , NULL );
188
+ * ((void * * )(& System_malloc )) =
189
+ utils_get_symbol_addr (System_library_handle , "malloc" , NULL );
190
+ * ((void * * )(& System_malloc_usable_size )) = utils_get_symbol_addr (
191
+ System_library_handle , "malloc_usable_size" , NULL );
192
+ * ((void * * )(& System_realloc )) =
193
+ utils_get_symbol_addr (System_library_handle , "realloc" , NULL );
194
+
195
+ if (System_aligned_alloc && System_calloc && System_free && System_malloc &&
196
+ System_malloc_usable_size && System_realloc ) {
197
+ return 0 ;
198
+ }
199
+
200
+ * ((void * * )(& System_aligned_alloc )) = NULL ;
201
+ * ((void * * )(& System_calloc )) = NULL ;
202
+ * ((void * * )(& System_free )) = NULL ;
203
+ * ((void * * )(& System_malloc )) = NULL ;
204
+ * ((void * * )(& System_malloc_usable_size )) = NULL ;
205
+ * ((void * * )(& System_realloc )) = NULL ;
206
+
207
+ return -1 ;
208
+ }
209
+
110
210
void proxy_lib_create_common (void ) {
111
211
utils_log_init ();
112
212
umf_os_memory_provider_params_t os_params =
113
213
umfOsMemoryProviderParamsDefault ();
114
214
umf_result_t umf_result ;
115
215
116
- #ifndef _WIN32
117
- char shm_name [NAME_MAX ];
216
+ size_t _threshold = get_size_threshold ();
217
+ if (_threshold > 0 ) {
218
+ if (get_system_allocator_symbols ()) {
219
+ LOG_ERR ("initialization of the system allocator failed!" );
220
+ exit (-1 );
221
+ }
222
+
223
+ Size_threshold_value = _threshold ;
224
+ LOG_INFO ("system allocator initialized, size threshold value = %zu" ,
225
+ Size_threshold_value );
226
+ }
118
227
228
+ #ifndef _WIN32
119
229
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" );
230
+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
231
+ "file descriptor duplication" );
122
232
os_params .visibility = UMF_MEM_MAP_SHARED ;
123
233
os_params .shm_name = NULL ;
124
234
125
235
} else if (utils_env_var_has_str ("UMF_PROXY" ,
126
236
"page.disposition=shared-shm" )) {
127
237
os_params .visibility = UMF_MEM_MAP_SHARED ;
128
238
239
+ char shm_name [NAME_MAX ];
129
240
memset (shm_name , 0 , NAME_MAX );
130
241
sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131
242
os_params .shm_name = shm_name ;
132
243
133
- LOG_DEBUG ("proxy_lib: using the MAP_SHARED visibility mode with the "
134
- "named shared memory: %s" ,
135
- os_params .shm_name );
244
+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
245
+ "named shared memory: %s" ,
246
+ os_params .shm_name );
136
247
}
137
- #endif
248
+ #endif /* _WIN32 */
138
249
139
250
umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140
251
& OS_memory_provider );
@@ -149,16 +260,18 @@ void proxy_lib_create_common(void) {
149
260
LOG_ERR ("creating UMF pool manager failed" );
150
261
exit (-1 );
151
262
}
263
+
152
264
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153
265
// the linear allocator and start using the UMF pool allocator from now on.
266
+ LOG_DEBUG ("proxy library initialized" );
154
267
}
155
268
156
269
void proxy_lib_destroy_common (void ) {
157
270
if (utils_is_running_in_proxy_lib ()) {
158
271
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159
272
// because it could lead to use-after-free in the program's unloader
160
273
// (for example _dl_fini() on Linux).
161
- return ;
274
+ goto fini_proxy_lib_destroy_common ;
162
275
}
163
276
164
277
umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +281,18 @@ void proxy_lib_destroy_common(void) {
168
281
umf_memory_provider_handle_t provider = OS_memory_provider ;
169
282
OS_memory_provider = NULL ;
170
283
umfMemoryProviderDestroy (provider );
284
+
285
+ #ifdef _WIN32
286
+ if (System_library_handle ) {
287
+ utils_close_library (System_library_handle );
288
+ System_library_handle = NULL ;
289
+ }
290
+ #endif /* _WIN32 */
291
+
292
+ LOG_DEBUG ("proxy library destroyed" );
293
+
294
+ fini_proxy_lib_destroy_common :
295
+ LOG_DEBUG ("proxy library finalized" );
171
296
}
172
297
173
298
/*****************************************************************************/
@@ -246,6 +371,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246
371
/*****************************************************************************/
247
372
248
373
void * malloc (size_t size ) {
374
+ if (size < Size_threshold_value ) {
375
+ return System_malloc (size );
376
+ }
377
+
249
378
if (!was_called_from_umfPool && Proxy_pool ) {
250
379
was_called_from_umfPool = 1 ;
251
380
void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +386,10 @@ void *malloc(size_t size) {
257
386
}
258
387
259
388
void * calloc (size_t nmemb , size_t size ) {
389
+ if ((nmemb * size ) < Size_threshold_value ) {
390
+ return System_calloc (nmemb , size );
391
+ }
392
+
260
393
if (!was_called_from_umfPool && Proxy_pool ) {
261
394
was_called_from_umfPool = 1 ;
262
395
void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +409,20 @@ void free(void *ptr) {
276
409
return ;
277
410
}
278
411
279
- if (Proxy_pool ) {
412
+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280
413
if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281
414
LOG_ERR ("umfPoolFree() failed" );
282
- assert (0 );
283
415
}
284
416
return ;
285
417
}
286
418
287
- assert (0 );
419
+ if (Size_threshold_value ) {
420
+ System_free (ptr );
421
+ return ;
422
+ }
423
+
424
+ LOG_ERR ("free() failed: %p" , ptr );
425
+
288
426
return ;
289
427
}
290
428
@@ -303,18 +441,27 @@ void *realloc(void *ptr, size_t size) {
303
441
return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304
442
}
305
443
306
- if (Proxy_pool ) {
444
+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307
445
was_called_from_umfPool = 1 ;
308
446
void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309
447
was_called_from_umfPool = 0 ;
310
448
return new_ptr ;
311
449
}
312
450
313
- assert (0 );
451
+ if (Size_threshold_value ) {
452
+ return System_realloc (ptr , size );
453
+ }
454
+
455
+ LOG_ERR ("realloc() failed: %p" , ptr );
456
+
314
457
return NULL ;
315
458
}
316
459
317
460
void * aligned_alloc (size_t alignment , size_t size ) {
461
+ if (size < Size_threshold_value ) {
462
+ return System_aligned_alloc (alignment , size );
463
+ }
464
+
318
465
if (!was_called_from_umfPool && Proxy_pool ) {
319
466
was_called_from_umfPool = 1 ;
320
467
void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +477,28 @@ size_t _msize(void *ptr) {
330
477
#else
331
478
size_t malloc_usable_size (void * ptr ) {
332
479
#endif
333
-
334
- // a check to verify we are running the proxy library
480
+ // a check to verify if we are running the proxy library
335
481
if (ptr == (void * )0x01 ) {
336
482
return 0xDEADBEEF ;
337
483
}
338
484
339
- if (!was_called_from_umfPool && Proxy_pool ) {
485
+ if (ba_leak_pool_contains_pointer (ptr )) {
486
+ return 0 ; // unsupported in case of the ba_leak allocator
487
+ }
488
+
489
+ if (Proxy_pool && (umfPoolByPtr (ptr ) == Proxy_pool )) {
340
490
was_called_from_umfPool = 1 ;
341
491
size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342
492
was_called_from_umfPool = 0 ;
343
493
return size ;
344
494
}
345
495
496
+ if (Size_threshold_value ) {
497
+ return System_malloc_usable_size (ptr );
498
+ }
499
+
500
+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
501
+
346
502
return 0 ; // unsupported in this case
347
503
}
348
504
0 commit comments