Skip to content

Commit e4872fa

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 e4872fa

File tree

2 files changed

+150
-17
lines changed

2 files changed

+150
-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: 140 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 handle
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,23 @@ 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 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+
98122
static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT;
99123
static umf_ba_linear_pool_t *Base_alloc_leak = NULL;
100124
static umf_memory_provider_handle_t OS_memory_provider = NULL;
@@ -107,34 +131,96 @@ static __TLS int was_called_from_umfPool = 0;
107131
/*** The constructor and destructor of the proxy library *********************/
108132
/*****************************************************************************/
109133

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 get_system_allocator_symbols(void) {
157+
#ifdef _WIN32
158+
void *handle = RTLD_NEXT;
159+
#else
160+
void *handle = RTLD_NEXT;
161+
#endif /* _WIN32 */
162+
163+
*((void **)(&System_aligned_alloc)) = utils_get_symbol_addr(handle, "aligned_alloc", NULL);
164+
*((void **)(&System_calloc)) = utils_get_symbol_addr(handle, "calloc", NULL);
165+
*((void **)(&System_free)) = utils_get_symbol_addr(handle, "free", NULL);
166+
*((void **)(&System_malloc)) = utils_get_symbol_addr(handle, "malloc", NULL);
167+
*((void **)(&System_malloc_usable_size)) = utils_get_symbol_addr(handle, "malloc_usable_size", NULL);
168+
*((void **)(&System_realloc)) = utils_get_symbol_addr(handle, "realloc", NULL);
169+
170+
if (System_aligned_alloc && System_calloc && System_free && System_malloc &&
171+
System_malloc_usable_size && System_realloc) {
172+
return 0;
173+
}
174+
175+
*((void **)(&System_aligned_alloc)) = NULL;
176+
*((void **)(&System_calloc)) = NULL;
177+
*((void **)(&System_free)) = NULL;
178+
*((void **)(&System_malloc)) = NULL;
179+
*((void **)(&System_malloc_usable_size)) = NULL;
180+
*((void **)(&System_realloc)) = NULL;
181+
182+
return -1;
183+
}
184+
110185
void proxy_lib_create_common(void) {
111186
utils_log_init();
112187
umf_os_memory_provider_params_t os_params =
113188
umfOsMemoryProviderParamsDefault();
114189
umf_result_t umf_result;
115190

116-
#ifndef _WIN32
117-
char shm_name[NAME_MAX];
191+
size_t _threshold = get_size_threshold();
192+
if (_threshold > 0) {
193+
if (get_system_allocator_symbols()) {
194+
LOG_ERR("initialization of the system allocator failed!");
195+
exit(-1);
196+
}
118197

198+
Size_threshold_value = _threshold;
199+
LOG_INFO("system allocator initialized, size threshold value = %zu",
200+
Size_threshold_value);
201+
}
202+
203+
#ifndef _WIN32
119204
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");
205+
LOG_INFO("proxy_lib: using the MAP_SHARED visibility mode with the "
206+
"file descriptor duplication");
122207
os_params.visibility = UMF_MEM_MAP_SHARED;
123208
os_params.shm_name = NULL;
124209

125210
} else if (utils_env_var_has_str("UMF_PROXY",
126211
"page.disposition=shared-shm")) {
127212
os_params.visibility = UMF_MEM_MAP_SHARED;
128213

214+
char shm_name[NAME_MAX];
129215
memset(shm_name, 0, NAME_MAX);
130216
sprintf(shm_name, "umf_proxy_lib_shm_pid_%i", utils_getpid());
131217
os_params.shm_name = shm_name;
132218

133-
LOG_DEBUG("proxy_lib: using the MAP_SHARED visibility mode with the "
134-
"named shared memory: %s",
135-
os_params.shm_name);
219+
LOG_INFO("proxy_lib: using the MAP_SHARED visibility mode with the "
220+
"named shared memory: %s",
221+
os_params.shm_name);
136222
}
137-
#endif
223+
#endif /* _WIN32 */
138224

139225
umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_params,
140226
&OS_memory_provider);
@@ -149,16 +235,18 @@ void proxy_lib_create_common(void) {
149235
LOG_ERR("creating UMF pool manager failed");
150236
exit(-1);
151237
}
238+
152239
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153240
// the linear allocator and start using the UMF pool allocator from now on.
241+
LOG_DEBUG("proxy library initialized");
154242
}
155243

156244
void proxy_lib_destroy_common(void) {
157245
if (utils_is_running_in_proxy_lib()) {
158246
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159247
// because it could lead to use-after-free in the program's unloader
160248
// (for example _dl_fini() on Linux).
161-
return;
249+
goto fini_proxy_lib_destroy_common;
162250
}
163251

164252
umf_memory_pool_handle_t pool = Proxy_pool;
@@ -168,6 +256,10 @@ void proxy_lib_destroy_common(void) {
168256
umf_memory_provider_handle_t provider = OS_memory_provider;
169257
OS_memory_provider = NULL;
170258
umfMemoryProviderDestroy(provider);
259+
LOG_DEBUG("proxy library destroyed");
260+
261+
fini_proxy_lib_destroy_common:
262+
LOG_DEBUG("proxy library finalized");
171263
}
172264

173265
/*****************************************************************************/
@@ -246,6 +338,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246338
/*****************************************************************************/
247339

248340
void *malloc(size_t size) {
341+
if (size < Size_threshold_value) {
342+
return System_malloc(size);
343+
}
344+
249345
if (!was_called_from_umfPool && Proxy_pool) {
250346
was_called_from_umfPool = 1;
251347
void *ptr = umfPoolMalloc(Proxy_pool, size);
@@ -257,6 +353,10 @@ void *malloc(size_t size) {
257353
}
258354

259355
void *calloc(size_t nmemb, size_t size) {
356+
if ((nmemb * size) < Size_threshold_value) {
357+
return System_calloc(nmemb, size);
358+
}
359+
260360
if (!was_called_from_umfPool && Proxy_pool) {
261361
was_called_from_umfPool = 1;
262362
void *ptr = umfPoolCalloc(Proxy_pool, nmemb, size);
@@ -276,15 +376,20 @@ void free(void *ptr) {
276376
return;
277377
}
278378

279-
if (Proxy_pool) {
379+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
280380
if (umfPoolFree(Proxy_pool, ptr) != UMF_RESULT_SUCCESS) {
281381
LOG_ERR("umfPoolFree() failed");
282-
assert(0);
283382
}
284383
return;
285384
}
286385

287-
assert(0);
386+
if (Size_threshold_value) {
387+
System_free(ptr);
388+
return;
389+
}
390+
391+
LOG_ERR("free() failed: %p", ptr);
392+
288393
return;
289394
}
290395

@@ -303,18 +408,27 @@ void *realloc(void *ptr, size_t size) {
303408
return ba_leak_realloc(ptr, size, leak_pool_contains_pointer);
304409
}
305410

306-
if (Proxy_pool) {
411+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
307412
was_called_from_umfPool = 1;
308413
void *new_ptr = umfPoolRealloc(Proxy_pool, ptr, size);
309414
was_called_from_umfPool = 0;
310415
return new_ptr;
311416
}
312417

313-
assert(0);
418+
if (Size_threshold_value) {
419+
return System_realloc(ptr, size);
420+
}
421+
422+
LOG_ERR("realloc() failed: %p", ptr);
423+
314424
return NULL;
315425
}
316426

317427
void *aligned_alloc(size_t alignment, size_t size) {
428+
if (size < Size_threshold_value) {
429+
return System_aligned_alloc(alignment, size);
430+
}
431+
318432
if (!was_called_from_umfPool && Proxy_pool) {
319433
was_called_from_umfPool = 1;
320434
void *ptr = umfPoolAlignedMalloc(Proxy_pool, size, alignment);
@@ -330,19 +444,28 @@ size_t _msize(void *ptr) {
330444
#else
331445
size_t malloc_usable_size(void *ptr) {
332446
#endif
333-
334-
// a check to verify we are running the proxy library
447+
// a check to verify if we are running the proxy library
335448
if (ptr == (void *)0x01) {
336449
return 0xDEADBEEF;
337450
}
338451

339-
if (!was_called_from_umfPool && Proxy_pool) {
452+
if (ba_leak_pool_contains_pointer(ptr)) {
453+
return 0; // unsupported in case of the ba_leak allocator
454+
}
455+
456+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
340457
was_called_from_umfPool = 1;
341458
size_t size = umfPoolMallocUsableSize(Proxy_pool, ptr);
342459
was_called_from_umfPool = 0;
343460
return size;
344461
}
345462

463+
if (Size_threshold_value) {
464+
return System_malloc_usable_size(ptr);
465+
}
466+
467+
LOG_ERR("malloc_usable_size() failed: %p", ptr);
468+
346469
return 0; // unsupported in this case
347470
}
348471

0 commit comments

Comments
 (0)