Skip to content

Commit 1abc22e

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 e02670e commit 1abc22e

File tree

2 files changed

+183
-17
lines changed

2 files changed

+183
-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: 173 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,120 @@ 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+
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+
110210
void proxy_lib_create_common(void) {
111211
utils_log_init();
112212
umf_os_memory_provider_params_t os_params =
113213
umfOsMemoryProviderParamsDefault();
114214
umf_result_t umf_result;
115215

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+
}
118227

228+
#ifndef _WIN32
119229
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");
122232
os_params.visibility = UMF_MEM_MAP_SHARED;
123233
os_params.shm_name = NULL;
124234

125235
} else if (utils_env_var_has_str("UMF_PROXY",
126236
"page.disposition=shared-shm")) {
127237
os_params.visibility = UMF_MEM_MAP_SHARED;
128238

239+
char shm_name[NAME_MAX];
129240
memset(shm_name, 0, NAME_MAX);
130241
sprintf(shm_name, "umf_proxy_lib_shm_pid_%i", utils_getpid());
131242
os_params.shm_name = shm_name;
132243

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);
136247
}
137-
#endif
248+
#endif /* _WIN32 */
138249

139250
umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_params,
140251
&OS_memory_provider);
@@ -149,16 +260,18 @@ void proxy_lib_create_common(void) {
149260
LOG_ERR("creating UMF pool manager failed");
150261
exit(-1);
151262
}
263+
152264
// The UMF pool has just been created (Proxy_pool != NULL). Stop using
153265
// the linear allocator and start using the UMF pool allocator from now on.
266+
LOG_DEBUG("proxy library initialized");
154267
}
155268

156269
void proxy_lib_destroy_common(void) {
157270
if (utils_is_running_in_proxy_lib()) {
158271
// We cannot destroy 'Base_alloc_leak' nor 'Proxy_pool' nor 'OS_memory_provider',
159272
// because it could lead to use-after-free in the program's unloader
160273
// (for example _dl_fini() on Linux).
161-
return;
274+
goto fini_proxy_lib_destroy_common;
162275
}
163276

164277
umf_memory_pool_handle_t pool = Proxy_pool;
@@ -168,6 +281,18 @@ void proxy_lib_destroy_common(void) {
168281
umf_memory_provider_handle_t provider = OS_memory_provider;
169282
OS_memory_provider = NULL;
170283
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");
171296
}
172297

173298
/*****************************************************************************/
@@ -246,6 +371,10 @@ static inline size_t ba_leak_pool_contains_pointer(void *ptr) {
246371
/*****************************************************************************/
247372

248373
void *malloc(size_t size) {
374+
if (size < Size_threshold_value) {
375+
return System_malloc(size);
376+
}
377+
249378
if (!was_called_from_umfPool && Proxy_pool) {
250379
was_called_from_umfPool = 1;
251380
void *ptr = umfPoolMalloc(Proxy_pool, size);
@@ -257,6 +386,10 @@ void *malloc(size_t size) {
257386
}
258387

259388
void *calloc(size_t nmemb, size_t size) {
389+
if ((nmemb * size) < Size_threshold_value) {
390+
return System_calloc(nmemb, size);
391+
}
392+
260393
if (!was_called_from_umfPool && Proxy_pool) {
261394
was_called_from_umfPool = 1;
262395
void *ptr = umfPoolCalloc(Proxy_pool, nmemb, size);
@@ -276,15 +409,20 @@ void free(void *ptr) {
276409
return;
277410
}
278411

279-
if (Proxy_pool) {
412+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
280413
if (umfPoolFree(Proxy_pool, ptr) != UMF_RESULT_SUCCESS) {
281414
LOG_ERR("umfPoolFree() failed");
282-
assert(0);
283415
}
284416
return;
285417
}
286418

287-
assert(0);
419+
if (Size_threshold_value) {
420+
System_free(ptr);
421+
return;
422+
}
423+
424+
LOG_ERR("free() failed: %p", ptr);
425+
288426
return;
289427
}
290428

@@ -303,18 +441,27 @@ void *realloc(void *ptr, size_t size) {
303441
return ba_leak_realloc(ptr, size, leak_pool_contains_pointer);
304442
}
305443

306-
if (Proxy_pool) {
444+
if (Proxy_pool && (umfPoolByPtr(ptr) == Proxy_pool)) {
307445
was_called_from_umfPool = 1;
308446
void *new_ptr = umfPoolRealloc(Proxy_pool, ptr, size);
309447
was_called_from_umfPool = 0;
310448
return new_ptr;
311449
}
312450

313-
assert(0);
451+
if (Size_threshold_value) {
452+
return System_realloc(ptr, size);
453+
}
454+
455+
LOG_ERR("realloc() failed: %p", ptr);
456+
314457
return NULL;
315458
}
316459

317460
void *aligned_alloc(size_t alignment, size_t size) {
461+
if (size < Size_threshold_value) {
462+
return System_aligned_alloc(alignment, size);
463+
}
464+
318465
if (!was_called_from_umfPool && Proxy_pool) {
319466
was_called_from_umfPool = 1;
320467
void *ptr = umfPoolAlignedMalloc(Proxy_pool, size, alignment);
@@ -330,19 +477,28 @@ size_t _msize(void *ptr) {
330477
#else
331478
size_t malloc_usable_size(void *ptr) {
332479
#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
335481
if (ptr == (void *)0x01) {
336482
return 0xDEADBEEF;
337483
}
338484

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)) {
340490
was_called_from_umfPool = 1;
341491
size_t size = umfPoolMallocUsableSize(Proxy_pool, ptr);
342492
was_called_from_umfPool = 0;
343493
return size;
344494
}
345495

496+
if (Size_threshold_value) {
497+
return System_malloc_usable_size(ptr);
498+
}
499+
500+
LOG_ERR("malloc_usable_size() failed: %p", ptr);
501+
346502
return 0; // unsupported in this case
347503
}
348504

0 commit comments

Comments
 (0)