Skip to content

Commit db760b2

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 ea00b4e commit db760b2

File tree

2 files changed

+146
-16
lines changed

2 files changed

+146
-16
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: 136 additions & 16 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
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
@@ -95,6 +101,23 @@ void utils_init_once(UTIL_ONCE_FLAG *flag, void (*onceCb)(void));
95101
* by an application.
96102
*/
97103

104+
typedef void *(*system_aligned_alloc_t)(size_t alignment, size_t size);
105+
typedef void *(*system_calloc_t)(size_t nmemb, size_t size);
106+
typedef void (*system_free_t)(void *ptr);
107+
typedef void *(*system_malloc_t)(size_t size);
108+
typedef size_t (*system_malloc_usable_size_t)(void *ptr);
109+
typedef void *(*system_realloc_t)(void *ptr, size_t size);
110+
111+
// pointers to the default system allocator's API
112+
static system_aligned_alloc_t System_aligned_alloc;
113+
static system_calloc_t System_calloc;
114+
static system_free_t System_free;
115+
static system_malloc_t System_malloc;
116+
static system_malloc_usable_size_t System_malloc_usable_size;
117+
static system_realloc_t System_realloc;
118+
119+
static size_t Size_threshold_value = 0;
120+
98121
static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT;
99122
static umf_ba_linear_pool_t *Base_alloc_leak = NULL;
100123
static umf_memory_provider_handle_t OS_memory_provider = NULL;
@@ -107,34 +130,93 @@ static __TLS int was_called_from_umfPool = 0;
107130
/*** The constructor and destructor of the proxy library *********************/
108131
/*****************************************************************************/
109132

133+
#ifndef _WIN32
134+
static size_t get_size_threshold(void) {
135+
char *str_threshold = utils_env_var_get_str("UMF_PROXY", "size.threshold=");
136+
if (!str_threshold) {
137+
return 0;
138+
}
139+
140+
// move to the beginning of the number
141+
str_threshold += strlen("size.threshold=");
142+
// find ';' at the end
143+
char *end = strstr(str_threshold, ";");
144+
if (end) {
145+
// replace ';' with '\0' to mark end of the string
146+
*end = '\0';
147+
}
148+
149+
size_t int_threshold = (size_t)atoi(str_threshold);
150+
LOG_DEBUG("Size_threshold_value = (char *) %s, (int) %zu", str_threshold,
151+
int_threshold);
152+
153+
return int_threshold;
154+
}
155+
156+
static int dlsym_system_allocator(void) {
157+
*((void **)(&System_aligned_alloc)) = dlsym(RTLD_NEXT, "aligned_alloc");
158+
*((void **)(&System_calloc)) = dlsym(RTLD_NEXT, "calloc");
159+
*((void **)(&System_free)) = dlsym(RTLD_NEXT, "free");
160+
*((void **)(&System_malloc)) = dlsym(RTLD_NEXT, "malloc");
161+
*((void **)(&System_malloc_usable_size)) =
162+
dlsym(RTLD_NEXT, "malloc_usable_size");
163+
*((void **)(&System_realloc)) = dlsym(RTLD_NEXT, "realloc");
164+
165+
if (System_aligned_alloc && System_calloc && System_free && System_malloc &&
166+
System_malloc_usable_size && System_realloc) {
167+
return 0;
168+
}
169+
170+
*((void **)(&System_aligned_alloc)) = NULL;
171+
*((void **)(&System_calloc)) = NULL;
172+
*((void **)(&System_free)) = NULL;
173+
*((void **)(&System_malloc)) = NULL;
174+
*((void **)(&System_malloc_usable_size)) = NULL;
175+
*((void **)(&System_realloc)) = NULL;
176+
177+
return -1;
178+
}
179+
#endif /* _WIN32 */
180+
110181
void proxy_lib_create_common(void) {
111182
utils_log_init();
112183
umf_os_memory_provider_params_t os_params =
113184
umfOsMemoryProviderParamsDefault();
114185
umf_result_t umf_result;
115186

116187
#ifndef _WIN32
117-
char shm_name[NAME_MAX];
188+
size_t _threshold = get_size_threshold();
189+
if (_threshold > 0) {
190+
if (dlsym_system_allocator()) {
191+
LOG_ERR("initialization of the system allocator failed!");
192+
exit(-1);
193+
}
194+
195+
Size_threshold_value = _threshold;
196+
LOG_INFO("system allocator initialized, size threshold value = %zu",
197+
Size_threshold_value);
198+
}
118199

119200
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");
201+
LOG_INFO("proxy_lib: using the MAP_SHARED visibility mode with the "
202+
"file descriptor duplication");
122203
os_params.visibility = UMF_MEM_MAP_SHARED;
123204
os_params.shm_name = NULL;
124205

125206
} else if (utils_env_var_has_str("UMF_PROXY",
126207
"page.disposition=shared-shm")) {
127208
os_params.visibility = UMF_MEM_MAP_SHARED;
128209

210+
char shm_name[NAME_MAX];
129211
memset(shm_name, 0, NAME_MAX);
130212
sprintf(shm_name, "umf_proxy_lib_shm_pid_%i", utils_getpid());
131213
os_params.shm_name = shm_name;
132214

133-
LOG_DEBUG("proxy_lib: using the MAP_SHARED visibility mode with the "
134-
"named shared memory: %s",
135-
os_params.shm_name);
215+
LOG_INFO("proxy_lib: using the MAP_SHARED visibility mode with the "
216+
"named shared memory: %s",
217+
os_params.shm_name);
136218
}
137-
#endif
219+
#endif /* _WIN32 */
138220

139221
umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_params,
140222
&OS_memory_provider);
@@ -149,16 +231,18 @@ void proxy_lib_create_common(void) {
149231
LOG_ERR("creating UMF pool manager failed");
150232
exit(-1);
151233
}
234+
152235
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153236
// the linear allocator and start using the UMF pool allocator from now on.
237+
LOG_DEBUG("proxy library initialized");
154238
}
155239

156240
void proxy_lib_destroy_common(void) {
157241
if (utils_is_running_in_proxy_lib()) {
158242
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159243
// because it could lead to use-after-free in the program's unloader
160244
// (for example _dl_fini() on Linux).
161-
return;
245+
goto fini_proxy_lib_destroy_common;
162246
}
163247

164248
umf_memory_pool_handle_t pool = Proxy_pool;
@@ -168,6 +252,10 @@ void proxy_lib_destroy_common(void) {
168252
umf_memory_provider_handle_t provider = OS_memory_provider;
169253
OS_memory_provider = NULL;
170254
umfMemoryProviderDestroy(provider);
255+
LOG_DEBUG("proxy library destroyed");
256+
257+
fini_proxy_lib_destroy_common:
258+
LOG_DEBUG("proxy library finalized");
171259
}
172260

173261
/*****************************************************************************/
@@ -246,6 +334,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246334
/*****************************************************************************/
247335

248336
void *malloc(size_t size) {
337+
if (size < Size_threshold_value) {
338+
return System_malloc(size);
339+
}
340+
249341
if (!was_called_from_umfPool && Proxy_pool) {
250342
was_called_from_umfPool = 1;
251343
void *ptr = umfPoolMalloc(Proxy_pool, size);
@@ -257,6 +349,10 @@ void *malloc(size_t size) {
257349
}
258350

259351
void *calloc(size_t nmemb, size_t size) {
352+
if ((nmemb * size) < Size_threshold_value) {
353+
return System_calloc(nmemb, size);
354+
}
355+
260356
if (!was_called_from_umfPool && Proxy_pool) {
261357
was_called_from_umfPool = 1;
262358
void *ptr = umfPoolCalloc(Proxy_pool, nmemb, size);
@@ -276,15 +372,20 @@ void free(void *ptr) {
276372
return;
277373
}
278374

279-
if (Proxy_pool) {
375+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
280376
if (umfPoolFree(Proxy_pool, ptr) != UMF_RESULT_SUCCESS) {
281377
LOG_ERR("umfPoolFree() failed");
282-
assert(0);
283378
}
284379
return;
285380
}
286381

287-
assert(0);
382+
if (Size_threshold_value) {
383+
System_free(ptr);
384+
return;
385+
}
386+
387+
LOG_ERR("free() failed: %p", ptr);
388+
288389
return;
289390
}
290391

@@ -303,18 +404,27 @@ void *realloc(void *ptr, size_t size) {
303404
return ba_leak_realloc(ptr, size, leak_pool_contains_pointer);
304405
}
305406

306-
if (Proxy_pool) {
407+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
307408
was_called_from_umfPool = 1;
308409
void *new_ptr = umfPoolRealloc(Proxy_pool, ptr, size);
309410
was_called_from_umfPool = 0;
310411
return new_ptr;
311412
}
312413

313-
assert(0);
414+
if (Size_threshold_value) {
415+
return System_realloc(ptr, size);
416+
}
417+
418+
LOG_ERR("realloc() failed: %p", ptr);
419+
314420
return NULL;
315421
}
316422

317423
void *aligned_alloc(size_t alignment, size_t size) {
424+
if (size < Size_threshold_value) {
425+
return System_aligned_alloc(alignment, size);
426+
}
427+
318428
if (!was_called_from_umfPool && Proxy_pool) {
319429
was_called_from_umfPool = 1;
320430
void *ptr = umfPoolAlignedMalloc(Proxy_pool, size, alignment);
@@ -330,19 +440,29 @@ size_t _msize(void *ptr) {
330440
#else
331441
size_t malloc_usable_size(void *ptr) {
332442
#endif
333-
334-
// a check to verify we are running the proxy library
443+
// a check to verify if we are running the proxy library
335444
if (ptr == (void *)0x01) {
336445
return 0xDEADBEEF;
337446
}
338447

339-
if (!was_called_from_umfPool && Proxy_pool) {
448+
if (ba_leak_pool_contains_pointer(ptr)) {
449+
return 0; // unsupported in case of the ba_leak allocator
450+
}
451+
452+
if (!was_called_from_umfPool && Proxy_pool &&
453+
(umfPoolByPtr(ptr) == Proxy_pool)) {
340454
was_called_from_umfPool = 1;
341455
size_t size = umfPoolMallocUsableSize(Proxy_pool, ptr);
342456
was_called_from_umfPool = 0;
343457
return size;
344458
}
345459

460+
if (Size_threshold_value) {
461+
return System_malloc_usable_size(ptr);
462+
}
463+
464+
LOG_ERR("malloc_usable_size() failed: %p", ptr);
465+
346466
return 0; // unsupported in this case
347467
}
348468

0 commit comments

Comments
 (0)