Skip to content

Commit 35d1da6

Browse files
committed
Add size threshold to proxy lib to call system allocator
Add a size threshold to proxy lib to call system allocator when the size is less than the given threshold. Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
1 parent 275af24 commit 35d1da6

File tree

2 files changed

+186
-17
lines changed

2 files changed

+186
-17
lines changed

.github/workflows/reusable_proxy_lib.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ jobs:
7777
working-directory: ${{env.BUILD_DIR}}
7878
run: UMF_PROXY="page.disposition=shared-shm" LD_PRELOAD=./lib/libumf_proxy.so /usr/bin/date
7979

80+
# TODO enable the provider_file_memory_ipc test when the IPC tests with the proxy library are fixed
81+
# see the issue: https://github.com/oneapi-src/unified-memory-framework/issues/864
82+
- name: Run "ctest --output-on-failure" with proxy library and size.threshold=128
83+
working-directory: ${{env.BUILD_DIR}}
84+
run: >
85+
UMF_PROXY="size.threshold=128"
86+
UMF_LOG="level:debug;flush:debug;output:stderr;pid:yes"
87+
LD_PRELOAD=./lib/libumf_proxy.so
88+
ctest --output-on-failure -E provider_file_memory_ipc
89+
8090
- name: Check coverage
8191
if: ${{ matrix.build_type == 'Debug' }}
8292
working-directory: ${{env.BUILD_DIR}}

src/proxy_lib/proxy_lib.c

Lines changed: 176 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
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
@@ -48,6 +54,7 @@
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+
98123
static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT;
99124
static umf_ba_linear_pool_t *Base_alloc_leak = NULL;
100125
static 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+
110213
void 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

156272
void 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

248376
void *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

259391
void *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

317463
void *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
331481
size_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

Comments
 (0)