Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add threshold to proxy lib to call system allocator #883

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
9 changes: 9 additions & 0 deletions .github/workflows/reusable_proxy_lib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ 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
- 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 -E provider_file_memory_ipc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should have a test where you use umfPoolByPtr() to check allocs smaller than threshold were not registered in the tracker

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a test for that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bratpiorka tests added
Done

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


- 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()) {
bratpiorka marked this conversation as resolved.
Show resolved Hide resolved
// We cannot destroy the TRACKER nor the base allocator
// when we are running in the proxy library with a size threshold,
// because it could result in calling the system free()
// with an invalid pointer and a segfault.
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