Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
needs: [Build]
uses: ./.github/workflows/reusable_benchmarks.yml
ProxyLib:
needs: [Build]
needs: [CodeChecks, DocsBuild]
uses: ./.github/workflows/reusable_proxy_lib.yml
Valgrind:
needs: [Build]
Expand Down
19 changes: 18 additions & 1 deletion .github/workflows/reusable_proxy_lib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,14 @@ jobs:

# TODO enable the provider_file_memory_ipc test when the IPC tests with the proxy library are fixed
# see the issue: https://github.com/oneapi-src/unified-memory-framework/issues/864
# TODO enable the proxy_lib_basic test for the JEMALLOC proxy_lib_pool
# see the issue: https://github.com/oneapi-src/unified-memory-framework/issues/894
- name: Run "ctest --output-on-failure" with proxy library
working-directory: ${{env.BUILD_DIR}}
run: LD_PRELOAD=./lib/libumf_proxy.so ctest --output-on-failure -E provider_file_memory_ipc
run: >
LD_PRELOAD=./lib/libumf_proxy.so
ctest --output-on-failure
${{ matrix.proxy_lib_pool == 'JEMALLOC' && '-E "provider_file_memory_ipc|proxy_lib_basic"' || '-E provider_file_memory_ipc' }}

- name: Run "./test/umf_test-memoryPool" with proxy library
working-directory: ${{env.BUILD_DIR}}
Expand All @@ -77,6 +82,18 @@ jobs:
working-directory: ${{env.BUILD_DIR}}
run: UMF_PROXY="page.disposition=shared-shm" LD_PRELOAD=./lib/libumf_proxy.so /usr/bin/date

# TODO enable the provider_file_memory_ipc test when the IPC tests with the proxy library are fixed
# see the issue: https://github.com/oneapi-src/unified-memory-framework/issues/864
# TODO enable the proxy_lib_basic test for the JEMALLOC proxy_lib_pool
# see the issue: https://github.com/oneapi-src/unified-memory-framework/issues/894
- name: Run "ctest --output-on-failure" with proxy library and size.threshold=128
working-directory: ${{env.BUILD_DIR}}
run: >
UMF_PROXY="size.threshold=128"
LD_PRELOAD=./lib/libumf_proxy.so
ctest --output-on-failure
${{ matrix.proxy_lib_pool == 'JEMALLOC' && '-E "provider_file_memory_ipc|proxy_lib_basic"' || '-E provider_file_memory_ipc' }}

- name: Check coverage
if: ${{ matrix.build_type == 'Debug' }}
working-directory: ${{env.BUILD_DIR}}
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ The memory used by the proxy memory allocator is mmap'ed:
- `page.disposition=shared-shm` - IPC uses the named shared memory. An SHM name is generated using the `umf_proxy_lib_shm_pid_$PID` pattern, where `$PID` is the PID of the process. It creates the `/dev/shm/umf_proxy_lib_shm_pid_$PID` file.
- `page.disposition=shared-fd` - IPC uses the file descriptor duplication. It requires using `pidfd_getfd(2)` to obtain a duplicate of another process's file descriptor. Permission to duplicate another process's file descriptor is governed by a ptrace access mode `PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`) that can be changed using the `/proc/sys/kernel/yama/ptrace_scope` interface. `pidfd_getfd(2)` is supported since Linux 5.6.

The **size threshold** feature (Linux only) can be enabled by adding the `size.threshold=<value>` string to the `UMF_PROXY` environment variable (with `';'` as a separator), for example: `UMF_PROXY="page.disposition=shared-shm;size.threshold=64"`.
It causes that all allocations of size less than the given threshold value go to the default system allocator instead of the proxy library.

#### Windows

In case of Windows it requires:
Expand Down
2 changes: 2 additions & 0 deletions src/base_alloc/base_alloc_global.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ static void umf_ba_create_global(void) {

size_t smallestSize = BASE_ALLOC.ac_sizes[0];
BASE_ALLOC.smallest_ac_size_log2 = log2Utils(smallestSize);

LOG_DEBUG("UMF base allocator created");
}

// returns index of the allocation class for a given size
Expand Down
24 changes: 24 additions & 0 deletions src/libumf.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ipc_cache.h"
#include "memspace_internal.h"
#include "provider_tracking.h"
#include "utils_common.h"
#include "utils_log.h"
#if !defined(UMF_NO_HWLOC)
#include "topology.h"
Expand All @@ -30,11 +31,20 @@ int umfInit(void) {
LOG_ERR("Failed to create memory tracker");
return -1;
}

LOG_DEBUG("UMF tracker created");

umf_result_t umf_result = umfIpcCacheGlobalInit();
if (umf_result != UMF_RESULT_SUCCESS) {
LOG_ERR("Failed to initialize IPC cache");
return -1;
}

LOG_DEBUG("UMF IPC cache initialized");
}

if (TRACKER) {
LOG_DEBUG("UMF library initialized");
}

return 0;
Expand All @@ -50,12 +60,26 @@ void umfTearDown(void) {
umfDestroyTopology();
#endif
umfIpcCacheGlobalTearDown();

if (utils_is_running_in_proxy_lib_with_size_threshold()) {
// We cannot destroy the TRACKER nor the base allocator
// when we are running in the proxy library with a size threshold,
// because it could lead to calling the system free() with an invalid pointer
// and a segfault as a result.
goto fini_umfTearDown;
}

// make sure TRACKER is not used after being destroyed
umf_memory_tracker_handle_t t = TRACKER;
TRACKER = NULL;
umfMemoryTrackerDestroy(t);
LOG_DEBUG("UMF tracker destroyed");

umf_ba_destroy_global();
LOG_DEBUG("UMF base allocator destroyed");

fini_umfTearDown:
LOG_DEBUG("UMF library finalized");
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/memory_provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ umf_result_t
umfMemoryProviderAllocationSplit(umf_memory_provider_handle_t hProvider,
void *ptr, size_t totalSize,
size_t firstSize) {
UMF_CHECK((hProvider != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);

if (!ptr) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
Expand All @@ -325,6 +327,8 @@ umf_result_t
umfMemoryProviderAllocationMerge(umf_memory_provider_handle_t hProvider,
void *lowPtr, void *highPtr,
size_t totalSize) {
UMF_CHECK((hProvider != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);

if (!lowPtr || !highPtr) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
Expand All @@ -334,7 +338,7 @@ umfMemoryProviderAllocationMerge(umf_memory_provider_handle_t hProvider,
if ((uintptr_t)lowPtr >= (uintptr_t)highPtr) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
if ((uintptr_t)highPtr - (uintptr_t)lowPtr > totalSize) {
if ((uintptr_t)highPtr - (uintptr_t)lowPtr >= totalSize) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

Expand Down
14 changes: 8 additions & 6 deletions src/provider/provider_tracking.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,19 @@ umf_memory_pool_handle_t umfMemoryTrackerGetPool(const void *ptr) {

umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
umf_alloc_info_t *pAllocInfo) {
assert(ptr);
assert(pAllocInfo);

if (ptr == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

if (TRACKER == NULL) {
LOG_ERR("tracker is not created");
LOG_ERR("tracker does not exist");
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

if (TRACKER->map == NULL) {
LOG_ERR("tracker's map is not created");
LOG_ERR("tracker's map does not exist");
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

Expand All @@ -124,9 +127,8 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
int found = critnib_find(TRACKER->map, (uintptr_t)ptr, FIND_LE,
(void *)&rkey, (void **)&rvalue);
if (!found || (uintptr_t)ptr >= rkey + rvalue->size) {
LOG_WARN("pointer %p not found in the "
"tracker, TRACKER=%p",
ptr, (void *)TRACKER);
LOG_DEBUG("pointer %p not found in the tracker, TRACKER=%p", ptr,
(void *)TRACKER);
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

Expand Down
Loading
Loading