diff --git a/.github/workflows/reusable_proxy_lib.yml b/.github/workflows/reusable_proxy_lib.yml index 56211b97d..3c1903ff9 100644 --- a/.github/workflows/reusable_proxy_lib.yml +++ b/.github/workflows/reusable_proxy_lib.yml @@ -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}} @@ -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}} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d24244ab0..54271d730 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -414,6 +414,9 @@ if(UMF_PROXY_LIB_ENABLED AND UMF_BUILD_SHARED_LIBRARY) SRCS ${BA_SOURCES_FOR_TEST} test_proxy_lib.cpp LIBS ${UMF_UTILS_FOR_TEST} umf_proxy) + set_property(TEST umf-proxy_lib_basic + PROPERTY ENVIRONMENT "UMF_PROXY=size.threshold=64") + # the memoryPool test run with the proxy library add_umf_test( NAME proxy_lib_memoryPool diff --git a/test/test_proxy_lib.cpp b/test/test_proxy_lib.cpp index 85afc65be..12f17ce5f 100644 --- a/test/test_proxy_lib.cpp +++ b/test/test_proxy_lib.cpp @@ -19,13 +19,14 @@ using umf_test::test; -#define SIZE_64 64 +// size threshold defined by the env variable UMF_PROXY="size.threshold=64" +#define SIZE_THRESHOLD 64 +#define SIZE_EQ (SIZE_THRESHOLD) +#define SIZE_LT (SIZE_THRESHOLD - 1) + #define ALIGN_1024 1024 TEST_F(test, proxyLib_basic) { - - ::free(::malloc(SIZE_64)); - // a check to verify we are running the proxy library void *ptr = (void *)0x01; @@ -41,46 +42,162 @@ TEST_F(test, proxyLib_basic) { } TEST_F(test, proxyLib_realloc_size0) { - // realloc(ptr, 0) == free (ptr) + // realloc(ptr, 0) == free(ptr) // realloc(ptr, 0) returns NULL - ASSERT_EQ(::realloc(::malloc(SIZE_64), 0), nullptr); + ASSERT_EQ(::realloc(::malloc(SIZE_EQ), 0), nullptr); } -TEST_F(test, proxyLib_malloc_usable_size) { - - void *ptr = ::malloc(SIZE_64); - ASSERT_NE(ptr, nullptr); - if (ptr == nullptr) { - // Fix for the following CodeQL's warning on Windows: - // 'ptr' could be '0': this does not adhere to the specification for the function '_msize'. - return; - } +// The proxyLib_size_threshold_* tests test the size threshold of the proxy library. +// The size threshold is set to SIZE_THRESHOLD bytes in this test, so all allocations of: +// 1) size < SIZE_THRESHOLD go through the default system allocator +// (umfPoolByPtr(ptr_size < SIZE_THRESHOLD) == nullptr) +// 2) size >= SIZE_THRESHOLD go through the proxy library allocator +// (umfPoolByPtr(ptr_size >= SIZE_THRESHOLD) != nullptr) +TEST_F(test, proxyLib_size_threshold_aligned_alloc) { #ifdef _WIN32 - size_t size = _msize(ptr); -#elif __APPLE__ - size_t size = ::malloc_size(ptr); + void *ptr_LT = _aligned_malloc(SIZE_LT, ALIGN_1024); + void *ptr_EQ = _aligned_malloc(SIZE_EQ, ALIGN_1024); #else - size_t size = ::malloc_usable_size(ptr); + void *ptr_LT = ::aligned_alloc(ALIGN_1024, SIZE_LT); + void *ptr_EQ = ::aligned_alloc(ALIGN_1024, SIZE_EQ); #endif - ASSERT_EQ((int)(size == 0 || size >= SIZE_64), 1); + ASSERT_NE(ptr_LT, nullptr); + ASSERT_NE(ptr_EQ, nullptr); - ::free(ptr); -} + // verify alignment + ASSERT_EQ((int)(IS_ALIGNED((uintptr_t)ptr_LT, ALIGN_1024)), 1); + ASSERT_EQ((int)(IS_ALIGNED((uintptr_t)ptr_EQ, ALIGN_1024)), 1); + +#ifndef _WIN32 /* the size threshold works only on Linux for now */ + // umfPoolByPtr(ptr_size_LT) == nullptr + ASSERT_EQ(umfPoolByPtr(ptr_LT), nullptr); +#endif + // umfPoolByPtr(ptr_size_EQ) != nullptr + ASSERT_NE(umfPoolByPtr(ptr_EQ), nullptr); -TEST_F(test, proxyLib_aligned_alloc) { #ifdef _WIN32 - void *ptr = _aligned_malloc(SIZE_64, ALIGN_1024); + _aligned_free(ptr_LT); + _aligned_free(ptr_EQ); #else - void *ptr = ::aligned_alloc(ALIGN_1024, SIZE_64); + ::free(ptr_LT); + ::free(ptr_EQ); +#endif +} + +TEST_F(test, proxyLib_size_threshold_malloc) { + void *ptr_LT = malloc(SIZE_LT); + void *ptr_EQ = malloc(SIZE_EQ); + + ASSERT_NE(ptr_LT, nullptr); + ASSERT_NE(ptr_EQ, nullptr); + +#ifndef _WIN32 /* the size threshold works only on Linux for now */ + // umfPoolByPtr(ptr_size_LT) == nullptr + ASSERT_EQ(umfPoolByPtr(ptr_LT), nullptr); +#endif + // umfPoolByPtr(ptr_size_EQ) != nullptr + ASSERT_NE(umfPoolByPtr(ptr_EQ), nullptr); + + ::free(ptr_LT); + ::free(ptr_EQ); +} + +TEST_F(test, proxyLib_size_threshold_calloc) { + void *ptr_LT = calloc(SIZE_LT, 1); + void *ptr_EQ = calloc(SIZE_EQ, 1); + + ASSERT_NE(ptr_LT, nullptr); + ASSERT_NE(ptr_EQ, nullptr); + +#ifndef _WIN32 /* the size threshold works only on Linux for now */ + // umfPoolByPtr(ptr_size_LT) == nullptr + ASSERT_EQ(umfPoolByPtr(ptr_LT), nullptr); +#endif + // umfPoolByPtr(ptr_size_EQ) != nullptr + ASSERT_NE(umfPoolByPtr(ptr_EQ), nullptr); + + ::free(ptr_LT); + ::free(ptr_EQ); +} + +TEST_F(test, proxyLib_size_threshold_realloc_up) { + void *ptr_LT = malloc(SIZE_LT); + void *ptr_EQ = malloc(SIZE_EQ); + + ASSERT_NE(ptr_LT, nullptr); + ASSERT_NE(ptr_EQ, nullptr); + + void *ptr_LT_r = realloc(ptr_LT, 2 * SIZE_LT); + void *ptr_EQ_r = realloc(ptr_EQ, 2 * SIZE_EQ); + + ASSERT_NE(ptr_LT_r, nullptr); + ASSERT_NE(ptr_EQ_r, nullptr); + +#ifndef _WIN32 /* the size threshold works only on Linux for now */ + // umfPoolByPtr(ptr_size_LT) == nullptr + ASSERT_EQ(umfPoolByPtr(ptr_LT_r), nullptr); #endif + // umfPoolByPtr(ptr_size_EQ) != nullptr + ASSERT_NE(umfPoolByPtr(ptr_EQ_r), nullptr); - ASSERT_EQ((int)(IS_ALIGNED((uintptr_t)ptr, ALIGN_1024)), 1); + ::free(ptr_LT_r); + ::free(ptr_EQ_r); +} + +TEST_F(test, proxyLib_size_threshold_realloc_down) { + void *ptr_LT = malloc(SIZE_LT); + void *ptr_EQ = malloc(SIZE_EQ); + + ASSERT_NE(ptr_LT, nullptr); + ASSERT_NE(ptr_EQ, nullptr); + + void *ptr_LT_r = realloc(ptr_LT, SIZE_LT / 2); + void *ptr_EQ_r = realloc(ptr_EQ, SIZE_EQ / 2); + + ASSERT_NE(ptr_LT_r, nullptr); + ASSERT_NE(ptr_EQ_r, nullptr); + +#ifndef _WIN32 /* the size threshold works only on Linux for now */ + // umfPoolByPtr(ptr_size_LT) == nullptr + ASSERT_EQ(umfPoolByPtr(ptr_LT_r), nullptr); +#endif + // umfPoolByPtr(ptr_size_EQ) != nullptr + ASSERT_NE(umfPoolByPtr(ptr_EQ_r), nullptr); + + ::free(ptr_LT_r); + ::free(ptr_EQ_r); +} + +TEST_F(test, proxyLib_size_threshold_malloc_usable_size) { + + void *ptr_LT = ::malloc(SIZE_LT); + void *ptr_EQ = ::malloc(SIZE_EQ); + + ASSERT_NE(ptr_LT, nullptr); + ASSERT_NE(ptr_EQ, nullptr); + + if (ptr_LT == nullptr || ptr_EQ == nullptr) { + // Fix for the following CodeQL's warning on Windows: + // 'ptr' could be '0': this does not adhere to the specification for the function '_msize'. + return; + } #ifdef _WIN32 - _aligned_free(ptr); + size_t size_LT = _msize(ptr_LT); + size_t size_EQ = _msize(ptr_EQ); +#elif __APPLE__ + size_t size_LT = ::malloc_size(ptr_LT); + size_t size_EQ = ::malloc_size(ptr_EQ); #else - ::free(ptr); + size_t size_LT = ::malloc_usable_size(ptr_LT); + size_t size_EQ = ::malloc_usable_size(ptr_EQ); #endif + + ASSERT_EQ((int)(size_LT == 0 || size_LT >= SIZE_LT), 1); + ASSERT_EQ((int)(size_EQ == 0 || size_EQ >= SIZE_EQ), 1); + + ::free(ptr_LT); + ::free(ptr_EQ); }