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 ***************************************/
@@ -94,6 +101,24 @@ void utils_init_once(UTIL_ONCE_FLAG *flag, void (*onceCb)(void));
94
101
* of a UMF pool to allocate memory needed by an application. It should be freed
95
102
* by an application.
96
103
*/
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 */
97
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 ;
@@ -107,34 +132,87 @@ static __TLS int was_called_from_umfPool = 0;
107
132
/*** The constructor and destructor of the proxy library *********************/
108
133
/*****************************************************************************/
109
134
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
+ LOG_DEBUG ("UMF_PROXY[size.threshold] = %s" , str_threshold );
139
+ long threshold = utils_get_size_threshold (str_threshold );
140
+ if (threshold < 0 ) {
141
+ LOG_ERR ("incorrect size threshold: %s" , str_threshold );
142
+ exit (-1 );
143
+ }
144
+
145
+ return (size_t )threshold ;
146
+ }
147
+
148
+ static int get_system_allocator_symbols (void ) {
149
+ * ((void * * )(& System_aligned_alloc )) =
150
+ utils_get_symbol_addr (RTLD_NEXT , "aligned_alloc" , NULL );
151
+ * ((void * * )(& System_calloc )) =
152
+ utils_get_symbol_addr (RTLD_NEXT , "calloc" , NULL );
153
+ * ((void * * )(& System_free )) = utils_get_symbol_addr (RTLD_NEXT , "free" , NULL );
154
+ * ((void * * )(& System_malloc )) =
155
+ utils_get_symbol_addr (RTLD_NEXT , "malloc" , NULL );
156
+ * ((void * * )(& System_malloc_usable_size )) =
157
+ utils_get_symbol_addr (RTLD_NEXT , "malloc_usable_size" , NULL );
158
+ * ((void * * )(& System_realloc )) =
159
+ utils_get_symbol_addr (RTLD_NEXT , "realloc" , NULL );
160
+
161
+ if (System_aligned_alloc && System_calloc && System_free && System_malloc &&
162
+ System_malloc_usable_size && System_realloc ) {
163
+ return 0 ;
164
+ }
165
+
166
+ * ((void * * )(& System_aligned_alloc )) = NULL ;
167
+ * ((void * * )(& System_calloc )) = NULL ;
168
+ * ((void * * )(& System_free )) = NULL ;
169
+ * ((void * * )(& System_malloc )) = NULL ;
170
+ * ((void * * )(& System_malloc_usable_size )) = NULL ;
171
+ * ((void * * )(& System_realloc )) = NULL ;
172
+
173
+ return -1 ;
174
+ }
175
+ #endif /* _WIN32 */
176
+
110
177
void proxy_lib_create_common (void ) {
111
178
utils_log_init ();
112
179
umf_os_memory_provider_params_t os_params =
113
180
umfOsMemoryProviderParamsDefault ();
114
181
umf_result_t umf_result ;
115
182
116
183
#ifndef _WIN32
117
- char shm_name [NAME_MAX ];
184
+ size_t _threshold = get_size_threshold ();
185
+ if (_threshold > 0 ) {
186
+ if (get_system_allocator_symbols ()) {
187
+ LOG_ERR ("initialization of the system allocator failed!" );
188
+ exit (-1 );
189
+ }
190
+
191
+ Size_threshold_value = _threshold ;
192
+ LOG_INFO ("system allocator initialized, size threshold value = %zu" ,
193
+ Size_threshold_value );
194
+ }
118
195
119
196
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" );
197
+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
198
+ "file descriptor duplication" );
122
199
os_params .visibility = UMF_MEM_MAP_SHARED ;
123
200
os_params .shm_name = NULL ;
124
201
125
202
} else if (utils_env_var_has_str ("UMF_PROXY" ,
126
203
"page.disposition=shared-shm" )) {
127
204
os_params .visibility = UMF_MEM_MAP_SHARED ;
128
205
206
+ char shm_name [NAME_MAX ];
129
207
memset (shm_name , 0 , NAME_MAX );
130
208
sprintf (shm_name , "umf_proxy_lib_shm_pid_%i" , utils_getpid ());
131
209
os_params .shm_name = shm_name ;
132
210
133
- LOG_DEBUG ("proxy_lib: using the MAP_SHARED visibility mode with the "
134
- "named shared memory: %s" ,
135
- os_params .shm_name );
211
+ LOG_INFO ("proxy_lib: using the MAP_SHARED visibility mode with the "
212
+ "named shared memory: %s" ,
213
+ os_params .shm_name );
136
214
}
137
- #endif
215
+ #endif /* _WIN32 */
138
216
139
217
umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (), & os_params ,
140
218
& OS_memory_provider );
@@ -149,16 +227,18 @@ void proxy_lib_create_common(void) {
149
227
LOG_ERR ("creating UMF pool manager failed" );
150
228
exit (-1 );
151
229
}
230
+
152
231
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153
232
// the linear allocator and start using the UMF pool allocator from now on.
233
+ LOG_DEBUG ("proxy library initialized" );
154
234
}
155
235
156
236
void proxy_lib_destroy_common (void ) {
157
237
if (utils_is_running_in_proxy_lib ()) {
158
238
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159
239
// because it could lead to use-after-free in the program's unloader
160
240
// (for example _dl_fini() on Linux).
161
- return ;
241
+ goto fini_proxy_lib_destroy_common ;
162
242
}
163
243
164
244
umf_memory_pool_handle_t pool = Proxy_pool ;
@@ -168,6 +248,10 @@ void proxy_lib_destroy_common(void) {
168
248
umf_memory_provider_handle_t provider = OS_memory_provider ;
169
249
OS_memory_provider = NULL ;
170
250
umfMemoryProviderDestroy (provider );
251
+ LOG_DEBUG ("proxy library destroyed" );
252
+
253
+ fini_proxy_lib_destroy_common :
254
+ LOG_DEBUG ("proxy library finalized" );
171
255
}
172
256
173
257
/*****************************************************************************/
@@ -246,6 +330,12 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246
330
/*****************************************************************************/
247
331
248
332
void * malloc (size_t size ) {
333
+ #ifndef _WIN32
334
+ if (size < Size_threshold_value ) {
335
+ return System_malloc (size );
336
+ }
337
+ #endif /* _WIN32 */
338
+
249
339
if (!was_called_from_umfPool && Proxy_pool ) {
250
340
was_called_from_umfPool = 1 ;
251
341
void * ptr = umfPoolMalloc (Proxy_pool , size );
@@ -257,6 +347,12 @@ void *malloc(size_t size) {
257
347
}
258
348
259
349
void * calloc (size_t nmemb , size_t size ) {
350
+ #ifndef _WIN32
351
+ if ((nmemb * size ) < Size_threshold_value ) {
352
+ return System_calloc (nmemb , size );
353
+ }
354
+ #endif /* _WIN32 */
355
+
260
356
if (!was_called_from_umfPool && Proxy_pool ) {
261
357
was_called_from_umfPool = 1 ;
262
358
void * ptr = umfPoolCalloc (Proxy_pool , nmemb , size );
@@ -276,15 +372,22 @@ void free(void *ptr) {
276
372
return ;
277
373
}
278
374
279
- if (Proxy_pool ) {
375
+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
280
376
if (umfPoolFree (Proxy_pool , ptr ) != UMF_RESULT_SUCCESS ) {
281
377
LOG_ERR ("umfPoolFree() failed" );
282
- assert (0 );
283
378
}
284
379
return ;
285
380
}
286
381
287
- assert (0 );
382
+ #ifndef _WIN32
383
+ if (Size_threshold_value ) {
384
+ System_free (ptr );
385
+ return ;
386
+ }
387
+ #endif /* _WIN32 */
388
+
389
+ LOG_ERR ("free() failed: %p" , ptr );
390
+
288
391
return ;
289
392
}
290
393
@@ -303,18 +406,31 @@ void *realloc(void *ptr, size_t size) {
303
406
return ba_leak_realloc (ptr , size , leak_pool_contains_pointer );
304
407
}
305
408
306
- if (Proxy_pool ) {
409
+ if (Proxy_pool && ( umfPoolByPtr ( ptr ) == Proxy_pool ) ) {
307
410
was_called_from_umfPool = 1 ;
308
411
void * new_ptr = umfPoolRealloc (Proxy_pool , ptr , size );
309
412
was_called_from_umfPool = 0 ;
310
413
return new_ptr ;
311
414
}
312
415
313
- assert (0 );
416
+ #ifndef _WIN32
417
+ if (Size_threshold_value ) {
418
+ return System_realloc (ptr , size );
419
+ }
420
+ #endif /* _WIN32 */
421
+
422
+ LOG_ERR ("realloc() failed: %p" , ptr );
423
+
314
424
return NULL ;
315
425
}
316
426
317
427
void * aligned_alloc (size_t alignment , size_t size ) {
428
+ #ifndef _WIN32
429
+ if (size < Size_threshold_value ) {
430
+ return System_aligned_alloc (alignment , size );
431
+ }
432
+ #endif /* _WIN32 */
433
+
318
434
if (!was_called_from_umfPool && Proxy_pool ) {
319
435
was_called_from_umfPool = 1 ;
320
436
void * ptr = umfPoolAlignedMalloc (Proxy_pool , size , alignment );
@@ -330,19 +446,30 @@ size_t _msize(void *ptr) {
330
446
#else
331
447
size_t malloc_usable_size (void * ptr ) {
332
448
#endif
333
-
334
- // a check to verify we are running the proxy library
449
+ // a check to verify if we are running the proxy library
335
450
if (ptr == (void * )0x01 ) {
336
451
return 0xDEADBEEF ;
337
452
}
338
453
339
- if (!was_called_from_umfPool && Proxy_pool ) {
454
+ if (ba_leak_pool_contains_pointer (ptr )) {
455
+ return 0 ; // unsupported in case of the ba_leak allocator
456
+ }
457
+
458
+ if (Proxy_pool && (umfPoolByPtr (ptr ) == Proxy_pool )) {
340
459
was_called_from_umfPool = 1 ;
341
460
size_t size = umfPoolMallocUsableSize (Proxy_pool , ptr );
342
461
was_called_from_umfPool = 0 ;
343
462
return size ;
344
463
}
345
464
465
+ #ifndef _WIN32
466
+ if (Size_threshold_value ) {
467
+ return System_malloc_usable_size (ptr );
468
+ }
469
+ #endif /* _WIN32 */
470
+
471
+ LOG_ERR ("malloc_usable_size() failed: %p" , ptr );
472
+
346
473
return 0 ; // unsupported in this case
347
474
}
348
475
0 commit comments