diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0918a3699..17fbaae41 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,7 +3,7 @@ name: GitHubPages on: push: - branches: ["main"] + branches: ["test_prealoads_llvm"] workflow_dispatch: # Cancel previous in-progress workflow, only the latest run is relevant @@ -15,8 +15,19 @@ permissions: contents: read jobs: + Benchmarks: + uses: ./.github/workflows/reusable_benchmarks.yml + permissions: + contents: read + pull-requests: write + with: + pr_no: '0' + bench_script_params: '--save baseline' + upload_report: true + DocsBuild: uses: ./.github/workflows/reusable_docs_build.yml + needs: Benchmarks with: upload: true diff --git a/.github/workflows/reusable_benchmarks.yml b/.github/workflows/reusable_benchmarks.yml index b41c99f3a..6d382e025 100644 --- a/.github/workflows/reusable_benchmarks.yml +++ b/.github/workflows/reusable_benchmarks.yml @@ -1,6 +1,5 @@ -# Executes benchmarks implemented in this repository -# using scripts for benchmark results visualization, -# which are downloaded from Unified Runtime repository. +# Executes benchmarks implemented in this repository using scripts +# for results visualization from intel/llvm (unified-runtime dir). name: Benchmarks on: @@ -31,9 +30,10 @@ env: jobs: benchmarks: name: Benchmarks + runs-on: ubuntu-latest # run only on upstream; forks will not have the HW - if: github.repository == 'oneapi-src/unified-memory-framework' - runs-on: L0_PERF + # if: github.repository == 'oneapi-src/unified-memory-framework' + # runs-on: L0_PERF steps: # Workspace on self-hosted runners is not cleaned automatically. @@ -44,6 +44,9 @@ jobs: ls -la ./ rm -rf ./* || true + - name: Install things + run: sudo apt-get install libhwloc-dev libjemalloc-dev libtbb-dev + - name: Add comment to PR uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: ${{ always() && inputs.pr_no != 0 }} @@ -98,50 +101,53 @@ jobs: - name: Build UMF run: cmake --build ${{env.BUILD_DIR}} -j $(nproc) - # We are going to clone Unified Runtime repository in order to run - # the most up-to-date UR scripts for benchmark data visualization - - name: Checkout UR + # Get scripts for benchmark data visualization. + # Use specific tag, as the scripts or files' location may change. + - name: Checkout SYCL uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - repository: oneapi-src/unified-runtime - path: ur-repo + repository: EuphoricThinking/llvm + ref: umf_preloaded_bench + path: sycl-repo fetch-depth: 1 - fetch-tags: false - - - name: Install pip packages for benchmarking scripts from UR - run: | - pip install --force-reinstall -r ${{github.workspace}}/ur-repo/third_party/benchmark_requirements.txt - - name: Set core range and GPU mask + - name: Install benchmarking scripts deps run: | - # Compute the core range for the second NUMA node; first node is for UR jobs. - # Skip the first 4 cores - the kernel is likely to schedule more work on these. - CORES=$(lscpu | awk ' - /NUMA node1 CPU|On-line CPU/ {line=$0} - END { - split(line, a, " ") - split(a[4], b, ",") - sub(/^0/, "4", b[1]) - print b[1] - }') - echo "Selected core: $CORES" - echo "CORES=$CORES" >> $GITHUB_ENV - - ZE_AFFINITY_MASK=1 - echo "ZE_AFFINITY_MASK=$ZE_AFFINITY_MASK" >> $GITHUB_ENV - - - name: Run UMF benchmarks (using scripts from UR) + pip install --force-reinstall -r ${{github.workspace}}/sycl-repo/unified-runtime/third_party/benchmark_requirements.txt + + # - name: Set core range and GPU mask + # run: | + # # Compute the core range for the second NUMA node; first node is for SYCL/UR jobs. + # # Skip the first 4 cores - the kernel is likely to schedule more work on these. + # CORES=$(lscpu | awk ' + # /NUMA node1 CPU|On-line CPU/ {line=$0} + # END { + # split(line, a, " ") + # split(a[4], b, ",") + # sub(/^0/, "4", b[1]) + # print b[1] + # }') + # echo "Selected core: $CORES" + # echo "CORES=$CORES" >> $GITHUB_ENV + + # ZE_AFFINITY_MASK=1 + # echo "ZE_AFFINITY_MASK=$ZE_AFFINITY_MASK" >> $GITHUB_ENV + + - name: Run UMF benchmarks id: benchmarks working-directory: ${{env.BUILD_DIR}} run: > - taskset -c ${{ env.CORES }} ${{ github.workspace }}/ur-repo/scripts/benchmarks/main.py + ${{ github.workspace }}/sycl-repo/unified-runtime/scripts/benchmarks/main.py ~/bench_workdir_umf --umf ${{env.BUILD_DIR}} + --compare baseline ${{ inputs.upload_report && '--output-html' || '' }} + ${{ inputs.pr_no != 0 && '--output-markdown' || '' }} ${{ inputs.bench_script_params }} + # In case it failed to add a comment, we can still print the results. - name: Print benchmark results - if: ${{ always() }} + if: ${{ always() && inputs.pr_no != 0 }} run: cat ${{env.BUILD_DIR}}/benchmark_results.md - name: Add comment to PR diff --git a/.github/workflows/reusable_compatibility.yml b/.github/workflows/reusable_compatibility.yml index fbd17a2f4..29597ac18 100644 --- a/.github/workflows/reusable_compatibility.yml +++ b/.github/workflows/reusable_compatibility.yml @@ -97,7 +97,6 @@ jobs: -DUMF_FORMAT_CODE_STYLE=OFF -DUMF_DEVELOPER_MODE=ON -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON - -DUMF_BUILD_LIBUMF_POOL_DISJOINT=ON -DUMF_TESTS_FAIL_ON_SKIP=ON - name: Build latest UMF @@ -197,7 +196,6 @@ jobs: -DUMF_FORMAT_CODE_STYLE=OFF -DUMF_DEVELOPER_MODE=ON -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON - -DUMF_BUILD_LIBUMF_POOL_DISJOINT=ON -DUMF_TESTS_FAIL_ON_SKIP=ON - name: Build latest UMF diff --git a/CMakeLists.txt b/CMakeLists.txt index 396a27c1e..ec10a0c4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,11 +186,12 @@ else() # --disable-initial-exec-tls - Disable the initial-exec TLS model for # jemalloc's internal thread-local storage (on those platforms that # support explicit settings). This can allow jemalloc to be dynamically - # loaded after program startup (e.g. using dlopen). + # loaded after program startup (e.g. using dlopen). --disable-doc - + # Disable building and installing the documentation. COMMAND ./configure --prefix=${jemalloc_targ_BINARY_DIR} --with-jemalloc-prefix=je_ --disable-cxx --disable-initial-exec-tls - CFLAGS=-fPIC + --disable-doc CFLAGS=-fPIC WORKING_DIRECTORY ${jemalloc_targ_SOURCE_DIR} OUTPUT ${jemalloc_targ_SOURCE_DIR}/Makefile DEPENDS ${jemalloc_targ_SOURCE_DIR}/configure) @@ -282,7 +283,8 @@ else() message(STATUS "hwloc CMAKE_GENERATOR: ${CMAKE_GENERATOR}") - if(CMAKE_GENERATOR STREQUAL "Ninja") + if(CMAKE_GENERATOR STREQUAL "Ninja" OR CMAKE_GENERATOR STREQUAL + "Unix Makefiles") add_custom_command( COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${hwloc_targ_BINARY_DIR} -B build @@ -407,7 +409,7 @@ if(UMF_BUILD_LEVEL_ZERO_PROVIDER AND (NOT UMF_LEVEL_ZERO_INCLUDE_DIR)) include(FetchContent) set(LEVEL_ZERO_LOADER_REPO "https://github.com/oneapi-src/level-zero.git") - set(LEVEL_ZERO_LOADER_TAG v1.19.2) + set(LEVEL_ZERO_LOADER_TAG v1.20.2) message( STATUS diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp index 3969b6068..60636a559 100644 --- a/benchmark/benchmark.cpp +++ b/benchmark/benchmark.cpp @@ -35,6 +35,10 @@ static void multithreaded(benchmark::internal::Benchmark *benchmark) { benchmark->Threads(1); } +static void singlethreaded(benchmark::internal::Benchmark *benchmark) { + benchmark->Threads(1); +} + static void default_multiple_alloc_fix_size(benchmark::internal::Benchmark *benchmark) { benchmark->Args({10000, 1, 4096}); @@ -68,7 +72,8 @@ UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark, proxy_pool, UMF_BENCHMARK_REGISTER_F(multiple_malloc_free_benchmark, proxy_pool) ->Apply(&default_multiple_alloc_fix_size) // reduce iterations, as this benchmark is slower than others - ->Iterations(50000); + ->Iterations(50000) + ->Apply(&singlethreaded); UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark, os_provider, fixed_alloc_size, @@ -76,7 +81,8 @@ UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark, os_provider, UMF_BENCHMARK_REGISTER_F(multiple_malloc_free_benchmark, os_provider) ->Apply(&default_multiple_alloc_fix_size) // reduce iterations, as this benchmark is slower than others - ->Iterations(50000); + ->Iterations(50000) + ->Apply(&singlethreaded); UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark, disjoint_pool_fix, fixed_alloc_size, @@ -89,7 +95,10 @@ UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark, disjoint_pool_uniform, uniform_alloc_size, pool_allocator>); UMF_BENCHMARK_REGISTER_F(multiple_malloc_free_benchmark, disjoint_pool_uniform) - ->Apply(&default_multiple_alloc_uniform_size); + ->Apply(&default_multiple_alloc_uniform_size) + ->Apply(&singlethreaded); +// TODO: change to multithreaded +//->Apply(&multithreaded); #ifdef UMF_POOL_JEMALLOC_ENABLED UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark, jemalloc_pool_fix, diff --git a/benchmark/benchmark_umf.hpp b/benchmark/benchmark_umf.hpp index 86cba4877..5c3b160c7 100644 --- a/benchmark/benchmark_umf.hpp +++ b/benchmark/benchmark_umf.hpp @@ -199,7 +199,7 @@ struct disjoint_pool : public pool_interface { return {nullptr, [](void *) {}}; } - ret = umfDisjointPoolParamsSetMinBucketSize(raw_params, 4096); + ret = umfDisjointPoolParamsSetMinBucketSize(raw_params, 8); if (ret != UMF_RESULT_SUCCESS) { state.SkipWithError("Failed to set min bucket size"); return {nullptr, [](void *) {}}; diff --git a/examples/ipc_level_zero/CMakeLists.txt b/examples/ipc_level_zero/CMakeLists.txt index d672d3e92..2aa391d65 100644 --- a/examples/ipc_level_zero/CMakeLists.txt +++ b/examples/ipc_level_zero/CMakeLists.txt @@ -24,7 +24,7 @@ endif() include(FetchContent) set(LEVEL_ZERO_LOADER_REPO "https://github.com/oneapi-src/level-zero.git") -set(LEVEL_ZERO_LOADER_TAG v1.19.2) +set(LEVEL_ZERO_LOADER_TAG v1.20.2) message( STATUS diff --git a/examples/level_zero_shared_memory/CMakeLists.txt b/examples/level_zero_shared_memory/CMakeLists.txt index f4aaf09e9..b7c990145 100644 --- a/examples/level_zero_shared_memory/CMakeLists.txt +++ b/examples/level_zero_shared_memory/CMakeLists.txt @@ -24,7 +24,7 @@ endif() include(FetchContent) set(LEVEL_ZERO_LOADER_REPO "https://github.com/oneapi-src/level-zero.git") -set(LEVEL_ZERO_LOADER_TAG v1.19.2) +set(LEVEL_ZERO_LOADER_TAG v1.20.2) message( STATUS diff --git a/src/coarse/coarse.c b/src/coarse/coarse.c index 0ce4ded3d..19798466e 100644 --- a/src/coarse/coarse.c +++ b/src/coarse/coarse.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -278,7 +278,7 @@ static block_t *node_list_rm_first(ravl_free_blocks_head_t *head_node, assert(node->prev == NULL); struct block_t *block = node->block; - if (IS_NOT_ALIGNED(block->size, alignment)) { + if (IS_NOT_ALIGNED(((uintptr_t)block->data), alignment)) { return NULL; } @@ -303,7 +303,7 @@ static block_t *node_list_rm_with_alignment(ravl_free_blocks_head_t *head_node, ravl_free_blocks_elem_t *node; for (node = head_node->head; node != NULL; node = node->next) { - if (IS_ALIGNED(node->block->size, alignment)) { + if (IS_ALIGNED(((uintptr_t)node->block->data), alignment)) { return node_list_rm(head_node, node); } } @@ -1170,10 +1170,13 @@ umf_result_t coarse_free(coarse_t *coarse, void *ptr, size_t bytes) { } block_t *block = get_node_block(node); - assert(block->used); + if (!block->used) { + LOG_ERR("double free"); + utils_mutex_unlock(&coarse->lock); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } if (bytes > 0 && bytes != block->size) { - // wrong size of allocation LOG_ERR("wrong size of allocation"); utils_mutex_unlock(&coarse->lock); return UMF_RESULT_ERROR_INVALID_ARGUMENT; diff --git a/src/ipc_cache.c b/src/ipc_cache.c index ccb296d5b..cab5fc478 100644 --- a/src/ipc_cache.c +++ b/src/ipc_cache.c @@ -144,6 +144,8 @@ umfIpcOpenedCacheCreate(ipc_opened_cache_eviction_cb_t eviction_cb) { void umfIpcOpenedCacheDestroy(ipc_opened_cache_handle_t cache) { ipc_opened_cache_entry_t *entry, *tmp; + + utils_mutex_lock(&(cache->global->cache_lock)); HASH_ITER(hh, cache->hash_table, entry, tmp) { DL_DELETE(cache->global->lru_list, entry); HASH_DEL(cache->hash_table, entry); @@ -153,6 +155,7 @@ void umfIpcOpenedCacheDestroy(ipc_opened_cache_handle_t cache) { umf_ba_free(cache->global->cache_allocator, entry); } HASH_CLEAR(hh, cache->hash_table); + utils_mutex_unlock(&(cache->global->cache_lock)); umf_ba_global_free(cache); } diff --git a/src/pool/pool_disjoint.c b/src/pool/pool_disjoint.c index 7aeee7165..9adb1a7a4 100644 --- a/src/pool/pool_disjoint.c +++ b/src/pool/pool_disjoint.c @@ -5,7 +5,23 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "base_alloc_global.h" #include "pool_disjoint_internal.h" +#include "provider/provider_tracking.h" +#include "uthash/utlist.h" +#include "utils_common.h" +#include "utils_log.h" +#include "utils_math.h" // Temporary solution for disabling memory poisoning. This is needed because // AddressSanitizer does not support memory poisoning for GPU allocations. @@ -94,9 +110,6 @@ static slab_t *create_slab(bucket_t *bucket) { goto free_slab_chunks; } - // TODO - // ASSERT_IS_ALIGNED((uintptr_t)slab->mem_ptr, bucket->size); - // raw allocation is not available for user so mark it as inaccessible utils_annotate_memory_inaccessible(slab->mem_ptr, slab->slab_size); @@ -175,10 +188,10 @@ static void slab_free_chunk(slab_t *slab, void *ptr) { // Make sure that we're in the right slab assert(ptr >= slab_get(slab) && ptr < slab_get_end(slab)); - // Even if the pointer p was previously aligned, it's still inside the - // corresponding chunk, so we get the correct index here. - size_t chunk_idx = - ((uintptr_t)ptr - (uintptr_t)slab->mem_ptr) / slab->bucket->size; + // Get the chunk index + uintptr_t ptr_diff = (uintptr_t)ptr - (uintptr_t)slab->mem_ptr; + assert((ptr_diff % slab->bucket->size) == 0); + size_t chunk_idx = ptr_diff / slab->bucket->size; // Make sure that the chunk was allocated assert(slab->chunks[chunk_idx] && "double free detected"); @@ -738,6 +751,12 @@ void *disjoint_pool_aligned_malloc(void *pool, size_t size, size_t alignment) { } } + void *aligned_ptr = (void *)ALIGN_UP_SAFE((size_t)ptr, alignment); + size_t diff = (ptrdiff_t)aligned_ptr - (ptrdiff_t)ptr; + size_t real_size = bucket->size - diff; + VALGRIND_DO_MEMPOOL_ALLOC(disjoint_pool, aligned_ptr, real_size); + utils_annotate_memory_undefined(aligned_ptr, real_size); + utils_mutex_unlock(&bucket->bucket_lock); if (disjoint_pool->params.pool_trace > 2) { @@ -746,18 +765,38 @@ void *disjoint_pool_aligned_malloc(void *pool, size_t size, size_t alignment) { (from_pool ? "pool" : "provider"), ptr); } - void *aligned_ptr = (void *)ALIGN_UP_SAFE((size_t)ptr, alignment); - VALGRIND_DO_MEMPOOL_ALLOC(disjoint_pool, aligned_ptr, size); - utils_annotate_memory_undefined(aligned_ptr, size); return aligned_ptr; } size_t disjoint_pool_malloc_usable_size(void *pool, void *ptr) { - (void)pool; - (void)ptr; + disjoint_pool_t *disjoint_pool = (disjoint_pool_t *)pool; + if (ptr == NULL) { + return 0; + } - // Not supported - return 0; + // check if given pointer is allocated inside any Disjoint Pool slab + slab_t *slab = + (slab_t *)critnib_find_le(disjoint_pool->known_slabs, (uintptr_t)ptr); + if (slab == NULL || ptr >= slab_get_end(slab)) { + // memory comes directly from the provider + umf_alloc_info_t allocInfo = {NULL, 0, NULL}; + umf_result_t ret = umfMemoryTrackerGetAllocInfo(ptr, &allocInfo); + if (ret != UMF_RESULT_SUCCESS) { + return 0; + } + + return allocInfo.baseSize; + } + // Get the unaligned pointer + // NOTE: the base pointer slab->mem_ptr needn't to be aligned to bucket size + size_t chunk_idx = + (((uintptr_t)ptr - (uintptr_t)slab->mem_ptr) / slab->bucket->size); + void *unaligned_ptr = + (void *)((uintptr_t)slab->mem_ptr + chunk_idx * slab->bucket->size); + + ptrdiff_t diff = (ptrdiff_t)ptr - (ptrdiff_t)unaligned_ptr; + + return slab->bucket->size - diff; } umf_result_t disjoint_pool_free(void *pool, void *ptr) { @@ -804,11 +843,18 @@ umf_result_t disjoint_pool_free(void *pool, void *ptr) { bucket_t *bucket = slab->bucket; - VALGRIND_DO_MEMPOOL_FREE(pool, ptr); utils_mutex_lock(&bucket->bucket_lock); + VALGRIND_DO_MEMPOOL_FREE(pool, ptr); + + // Get the unaligned pointer + // NOTE: the base pointer slab->mem_ptr needn't to be aligned to bucket size + size_t chunk_idx = + (((uintptr_t)ptr - (uintptr_t)slab->mem_ptr) / slab->bucket->size); + void *unaligned_ptr = + (void *)((uintptr_t)slab->mem_ptr + chunk_idx * slab->bucket->size); - utils_annotate_memory_inaccessible(ptr, bucket->size); - bucket_free_chunk(bucket, ptr, slab, &to_pool); + utils_annotate_memory_inaccessible(unaligned_ptr, bucket->size); + bucket_free_chunk(bucket, unaligned_ptr, slab, &to_pool); if (disjoint_pool->params.pool_trace > 1) { bucket->free_count++; diff --git a/src/pool/pool_disjoint_internal.h b/src/pool/pool_disjoint_internal.h index 3d656689c..86460509b 100644 --- a/src/pool/pool_disjoint_internal.h +++ b/src/pool/pool_disjoint_internal.h @@ -8,27 +8,12 @@ #ifndef UMF_POOL_DISJOINT_INTERNAL_H #define UMF_POOL_DISJOINT_INTERNAL_H 1 -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include "critnib/critnib.h" -#include "uthash/utlist.h" - -#include "base_alloc_global.h" -#include "provider/provider_tracking.h" -#include "utils_common.h" #include "utils_concurrency.h" -#include "utils_log.h" -#include "utils_math.h" typedef struct bucket_t bucket_t; typedef struct slab_t slab_t; diff --git a/src/provider/provider_tracking.c b/src/provider/provider_tracking.c index 73a03fb2d..f9a98e87f 100644 --- a/src/provider/provider_tracking.c +++ b/src/provider/provider_tracking.c @@ -291,26 +291,26 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr, tracker_alloc_info_t *lowValue = (tracker_alloc_info_t *)critnib_get( provider->hTracker->alloc_segments_map, (uintptr_t)lowPtr); if (!lowValue) { - LOG_ERR("no left value"); + LOG_FATAL("no left value"); ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; - goto err; + goto err_assert; } tracker_alloc_info_t *highValue = (tracker_alloc_info_t *)critnib_get( provider->hTracker->alloc_segments_map, (uintptr_t)highPtr); if (!highValue) { - LOG_ERR("no right value"); + LOG_FATAL("no right value"); ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; - goto err; + goto err_assert; } if (lowValue->pool != highValue->pool) { - LOG_ERR("pool mismatch"); + LOG_FATAL("pool mismatch"); ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; - goto err; + goto err_assert; } if (lowValue->size + highValue->size != totalSize) { - LOG_ERR("lowValue->size + highValue->size != totalSize"); + LOG_FATAL("lowValue->size + highValue->size != totalSize"); ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; - goto err; + goto err_assert; } ret = umfMemoryProviderAllocationMerge(provider->hUpstream, lowPtr, highPtr, @@ -342,7 +342,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr, return UMF_RESULT_SUCCESS; -err: +err_assert: assert(0); not_merged: @@ -473,10 +473,6 @@ static void trackingFinalize(void *provider) { critnib_delete(p->ipcCache); -#ifndef NDEBUG - check_if_tracker_is_empty(p->hTracker, p->pool); -#endif /* NDEBUG */ - umf_ba_global_free(provider); } diff --git a/test/coarse_lib.cpp b/test/coarse_lib.cpp index c5e30ee8f..c2e1f9c85 100644 --- a/test/coarse_lib.cpp +++ b/test/coarse_lib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -160,6 +160,13 @@ TEST_P(CoarseWithMemoryStrategyTest, coarseTest_basic_provider) { ASSERT_EQ(coarse_get_stats(ch).alloc_size, alloc_size); ASSERT_EQ(coarse_get_stats(ch).num_all_blocks, 1); + // test double free + umf_result = coarse_free(ch, ptr, 2 * MB); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); + ASSERT_EQ(coarse_get_stats(ch).used_size, 0); + ASSERT_EQ(coarse_get_stats(ch).alloc_size, alloc_size); + ASSERT_EQ(coarse_get_stats(ch).num_all_blocks, 1); + coarse_delete(ch); umfMemoryProviderDestroy(malloc_memory_provider); } @@ -202,6 +209,13 @@ TEST_P(CoarseWithMemoryStrategyTest, coarseTest_basic_fixed_memory) { ASSERT_EQ(coarse_get_stats(ch).alloc_size, buff_size); ASSERT_EQ(coarse_get_stats(ch).num_all_blocks, 1); + // test double free + umf_result = coarse_free(ch, ptr, 2 * MB); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); + ASSERT_EQ(coarse_get_stats(ch).used_size, 0); + ASSERT_EQ(coarse_get_stats(ch).alloc_size, buff_size); + ASSERT_EQ(coarse_get_stats(ch).num_all_blocks, 1); + coarse_delete(ch); } @@ -1349,3 +1363,48 @@ TEST_P(CoarseWithMemoryStrategyTest, coarseTest_alignment_fixed_memory) { coarse_delete(ch); } + +TEST_P(CoarseWithMemoryStrategyTest, + coarseTest_basic_non_aligned_fixed_memory) { + // preallocate some memory and initialize the vector with zeros + const size_t buff_size = 20 * MB + coarse_params.page_size; + std::vector buffer(buff_size, 0); + + void *buf_aligned = (void *)ALIGN_UP_SAFE((uintptr_t)buffer.data(), + coarse_params.page_size); + ASSERT_NE(buf_aligned, nullptr); + + void *buf_non_aligned = (void *)((uintptr_t)buf_aligned + 64); + size_t buf_non_aligned_size = + buff_size - ((uintptr_t)buf_non_aligned - (uintptr_t)buffer.data()); + buf_non_aligned_size = + ALIGN_DOWN(buf_non_aligned_size, coarse_params.page_size); + + coarse_params.cb.alloc = NULL; + coarse_params.cb.free = NULL; + + umf_result = coarse_new(&coarse_params, &coarse_handle); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + ASSERT_NE(coarse_handle, nullptr); + + coarse_t *ch = coarse_handle; + char *ptr = nullptr; + + umf_result = + coarse_add_memory_fixed(ch, buf_non_aligned, buf_non_aligned_size); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + ASSERT_EQ(coarse_get_stats(ch).used_size, 0 * MB); + ASSERT_EQ(coarse_get_stats(ch).alloc_size, buf_non_aligned_size); + ASSERT_EQ(coarse_get_stats(ch).num_all_blocks, 1); + + umf_result = coarse_alloc(ch, buf_non_aligned_size, 0, (void **)&ptr); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY); + ASSERT_EQ(ptr, nullptr); + + ASSERT_EQ(coarse_get_stats(ch).used_size, 0 * MB); + ASSERT_EQ(coarse_get_stats(ch).alloc_size, buf_non_aligned_size); + ASSERT_EQ(coarse_get_stats(ch).num_all_blocks, 1); + + coarse_delete(ch); +} diff --git a/test/common/pool.hpp b/test/common/pool.hpp index 9a5739085..a5b4afc15 100644 --- a/test/common/pool.hpp +++ b/test/common/pool.hpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023-2024 Intel Corporation + * Copyright (C) 2023-2025 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -19,6 +19,7 @@ #include #include +#include #include "base.hpp" #include "cpp_helpers.hpp" @@ -150,6 +151,49 @@ struct malloc_pool : public pool_base_t { umf_memory_pool_ops_t MALLOC_POOL_OPS = umf::poolMakeCOps(); +static constexpr size_t DEFAULT_DISJOINT_SLAB_MIN_SIZE = 4096; +static constexpr size_t DEFAULT_DISJOINT_MAX_POOLABLE_SIZE = 4096; +static constexpr size_t DEFAULT_DISJOINT_CAPACITY = 4; +static constexpr size_t DEFAULT_DISJOINT_MIN_BUCKET_SIZE = 64; + +inline void *defaultDisjointPoolConfig() { + umf_disjoint_pool_params_handle_t config = nullptr; + umf_result_t res = umfDisjointPoolParamsCreate(&config); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error("Failed to create pool params"); + } + res = umfDisjointPoolParamsSetSlabMinSize(config, + DEFAULT_DISJOINT_SLAB_MIN_SIZE); + if (res != UMF_RESULT_SUCCESS) { + umfDisjointPoolParamsDestroy(config); + throw std::runtime_error("Failed to set slab min size"); + } + res = umfDisjointPoolParamsSetMaxPoolableSize( + config, DEFAULT_DISJOINT_MAX_POOLABLE_SIZE); + if (res != UMF_RESULT_SUCCESS) { + umfDisjointPoolParamsDestroy(config); + throw std::runtime_error("Failed to set max poolable size"); + } + res = umfDisjointPoolParamsSetCapacity(config, DEFAULT_DISJOINT_CAPACITY); + if (res != UMF_RESULT_SUCCESS) { + umfDisjointPoolParamsDestroy(config); + throw std::runtime_error("Failed to set capacity"); + } + res = umfDisjointPoolParamsSetMinBucketSize( + config, DEFAULT_DISJOINT_MIN_BUCKET_SIZE); + if (res != UMF_RESULT_SUCCESS) { + umfDisjointPoolParamsDestroy(config); + throw std::runtime_error("Failed to set min bucket size"); + } + + return config; +} + +inline umf_result_t defaultDisjointPoolConfigDestroy(void *config) { + return umfDisjointPoolParamsDestroy( + static_cast(config)); +} + } // namespace umf_test #endif /* UMF_TEST_POOL_HPP */ diff --git a/test/ipcFixtures.hpp b/test/ipcFixtures.hpp index cfe58a166..57bd04079 100644 --- a/test/ipcFixtures.hpp +++ b/test/ipcFixtures.hpp @@ -15,8 +15,10 @@ #include #include +#include #include #include +#include #include class MemoryAccessor { @@ -158,6 +160,110 @@ struct umfIpcTest : umf_test::test, umf_memory_provider_ops_t *providerOps = nullptr; pfnProviderParamsCreate providerParamsCreate = nullptr; pfnProviderParamsDestroy providerParamsDestroy = nullptr; + + void concurrentGetConcurrentPutHandles(bool shuffle) { + std::vector ptrs; + constexpr size_t ALLOC_SIZE = 100; + constexpr size_t NUM_POINTERS = 100; + umf::pool_unique_handle_t pool = makePool(); + ASSERT_NE(pool.get(), nullptr); + + for (size_t i = 0; i < NUM_POINTERS; ++i) { + void *ptr = umfPoolMalloc(pool.get(), ALLOC_SIZE); + EXPECT_NE(ptr, nullptr); + ptrs.push_back(ptr); + } + + std::array, NTHREADS> ipcHandles; + + umf_test::syncthreads_barrier syncthreads(NTHREADS); + + auto getHandlesFn = [shuffle, &ipcHandles, &ptrs, + &syncthreads](size_t tid) { + // Each thread gets a copy of the pointers to shuffle them + std::vector localPtrs = ptrs; + if (shuffle) { + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(localPtrs.begin(), localPtrs.end(), g); + } + syncthreads(); + for (void *ptr : localPtrs) { + umf_ipc_handle_t ipcHandle; + size_t handleSize; + umf_result_t ret = + umfGetIPCHandle(ptr, &ipcHandle, &handleSize); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ipcHandles[tid].push_back(ipcHandle); + } + }; + + umf_test::parallel_exec(NTHREADS, getHandlesFn); + + auto putHandlesFn = [&ipcHandles, &syncthreads](size_t tid) { + syncthreads(); + for (umf_ipc_handle_t ipcHandle : ipcHandles[tid]) { + umf_result_t ret = umfPutIPCHandle(ipcHandle); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + } + }; + + umf_test::parallel_exec(NTHREADS, putHandlesFn); + + for (void *ptr : ptrs) { + umf_result_t ret = umfPoolFree(pool.get(), ptr); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + } + + pool.reset(nullptr); + EXPECT_EQ(stat.putCount, stat.getCount); + } + + void concurrentGetPutHandles(bool shuffle) { + std::vector ptrs; + constexpr size_t ALLOC_SIZE = 100; + constexpr size_t NUM_POINTERS = 100; + umf::pool_unique_handle_t pool = makePool(); + ASSERT_NE(pool.get(), nullptr); + + for (size_t i = 0; i < NUM_POINTERS; ++i) { + void *ptr = umfPoolMalloc(pool.get(), ALLOC_SIZE); + EXPECT_NE(ptr, nullptr); + ptrs.push_back(ptr); + } + + umf_test::syncthreads_barrier syncthreads(NTHREADS); + + auto getPutHandlesFn = [shuffle, &ptrs, &syncthreads](size_t) { + // Each thread gets a copy of the pointers to shuffle them + std::vector localPtrs = ptrs; + if (shuffle) { + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(localPtrs.begin(), localPtrs.end(), g); + } + syncthreads(); + for (void *ptr : localPtrs) { + umf_ipc_handle_t ipcHandle; + size_t handleSize; + umf_result_t ret = + umfGetIPCHandle(ptr, &ipcHandle, &handleSize); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ret = umfPutIPCHandle(ipcHandle); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + } + }; + + umf_test::parallel_exec(NTHREADS, getPutHandlesFn); + + for (void *ptr : ptrs) { + umf_result_t ret = umfPoolFree(pool.get(), ptr); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + } + + pool.reset(nullptr); + EXPECT_EQ(stat.putCount, stat.getCount); + } }; TEST_P(umfIpcTest, GetIPCHandleSize) { @@ -473,53 +579,18 @@ TEST_P(umfIpcTest, openInTwoIpcHandlers) { EXPECT_EQ(stat.closeCount, stat.openCount); } -TEST_P(umfIpcTest, ConcurrentGetPutHandles) { - std::vector ptrs; - constexpr size_t ALLOC_SIZE = 100; - constexpr size_t NUM_POINTERS = 100; - umf::pool_unique_handle_t pool = makePool(); - ASSERT_NE(pool.get(), nullptr); - - for (size_t i = 0; i < NUM_POINTERS; ++i) { - void *ptr = umfPoolMalloc(pool.get(), ALLOC_SIZE); - EXPECT_NE(ptr, nullptr); - ptrs.push_back(ptr); - } - - std::array, NTHREADS> ipcHandles; - - umf_test::syncthreads_barrier syncthreads(NTHREADS); - - auto getHandlesFn = [&ipcHandles, &ptrs, &syncthreads](size_t tid) { - syncthreads(); - for (void *ptr : ptrs) { - umf_ipc_handle_t ipcHandle; - size_t handleSize; - umf_result_t ret = umfGetIPCHandle(ptr, &ipcHandle, &handleSize); - ASSERT_EQ(ret, UMF_RESULT_SUCCESS); - ipcHandles[tid].push_back(ipcHandle); - } - }; - - umf_test::parallel_exec(NTHREADS, getHandlesFn); - - auto putHandlesFn = [&ipcHandles, &syncthreads](size_t tid) { - syncthreads(); - for (umf_ipc_handle_t ipcHandle : ipcHandles[tid]) { - umf_result_t ret = umfPutIPCHandle(ipcHandle); - EXPECT_EQ(ret, UMF_RESULT_SUCCESS); - } - }; +TEST_P(umfIpcTest, ConcurrentGetConcurrentPutHandles) { + concurrentGetConcurrentPutHandles(false); +} - umf_test::parallel_exec(NTHREADS, putHandlesFn); +TEST_P(umfIpcTest, ConcurrentGetConcurrentPutHandlesShuffled) { + concurrentGetConcurrentPutHandles(true); +} - for (void *ptr : ptrs) { - umf_result_t ret = umfPoolFree(pool.get(), ptr); - EXPECT_EQ(ret, UMF_RESULT_SUCCESS); - } +TEST_P(umfIpcTest, ConcurrentGetPutHandles) { concurrentGetPutHandles(false); } - pool.reset(nullptr); - EXPECT_EQ(stat.putCount, stat.getCount); +TEST_P(umfIpcTest, ConcurrentGetPutHandlesShuffled) { + concurrentGetPutHandles(true); } TEST_P(umfIpcTest, ConcurrentOpenCloseHandles) { @@ -593,4 +664,73 @@ TEST_P(umfIpcTest, ConcurrentOpenCloseHandles) { EXPECT_EQ(stat.openCount, stat.closeCount); } +TEST_P(umfIpcTest, ConcurrentDestroyIpcHandlers) { + constexpr size_t SIZE = 100; + constexpr size_t NUM_ALLOCS = 100; + constexpr size_t NUM_POOLS = 10; + void *ptrs[NUM_ALLOCS]; + void *openedPtrs[NUM_POOLS][NUM_ALLOCS]; + std::vector consumerPools; + umf::pool_unique_handle_t producerPool = makePool(); + ASSERT_NE(producerPool.get(), nullptr); + + for (size_t i = 0; i < NUM_POOLS; ++i) { + consumerPools.push_back(makePool()); + } + + for (size_t i = 0; i < NUM_ALLOCS; ++i) { + void *ptr = umfPoolMalloc(producerPool.get(), SIZE); + ASSERT_NE(ptr, nullptr); + ptrs[i] = ptr; + } + + for (size_t i = 0; i < NUM_ALLOCS; ++i) { + umf_ipc_handle_t ipcHandle = nullptr; + size_t handleSize = 0; + umf_result_t ret = umfGetIPCHandle(ptrs[i], &ipcHandle, &handleSize); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + for (size_t poolId = 0; poolId < NUM_POOLS; poolId++) { + void *ptr = nullptr; + umf_ipc_handler_handle_t ipcHandler = nullptr; + ret = + umfPoolGetIPCHandler(consumerPools[poolId].get(), &ipcHandler); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ipcHandler, nullptr); + + ret = umfOpenIPCHandle(ipcHandler, ipcHandle, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + openedPtrs[poolId][i] = ptr; + } + + ret = umfPutIPCHandle(ipcHandle); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + } + + for (size_t poolId = 0; poolId < NUM_POOLS; poolId++) { + for (size_t i = 0; i < NUM_ALLOCS; ++i) { + umf_result_t ret = umfCloseIPCHandle(openedPtrs[poolId][i]); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + } + } + + for (size_t i = 0; i < NUM_ALLOCS; ++i) { + umf_result_t ret = umfFree(ptrs[i]); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + } + + // Destroy pools in parallel to cause IPC cache cleanup in parallel. + umf_test::syncthreads_barrier syncthreads(NUM_POOLS); + auto poolDestroyFn = [&consumerPools, &syncthreads](size_t tid) { + syncthreads(); + consumerPools[tid].reset(nullptr); + }; + umf_test::parallel_exec(NUM_POOLS, poolDestroyFn); + + producerPool.reset(nullptr); + + EXPECT_EQ(stat.putCount, stat.getCount); + EXPECT_EQ(stat.openCount, stat.closeCount); +} + #endif /* UMF_TEST_IPC_FIXTURES_HPP */ diff --git a/test/memoryPoolAPI.cpp b/test/memoryPoolAPI.cpp index e2455fe85..a949b281f 100644 --- a/test/memoryPoolAPI.cpp +++ b/test/memoryPoolAPI.cpp @@ -12,6 +12,7 @@ #include "test_helpers.h" #include +#include #include #ifdef UMF_PROXY_LIB_ENABLED @@ -295,12 +296,14 @@ TEST_F(tagTest, SetAndGetInvalidPool) { INSTANTIATE_TEST_SUITE_P( mallocPoolTest, umfPoolTest, - ::testing::Values(poolCreateExtParams{&MALLOC_POOL_OPS, nullptr, nullptr, - &UMF_NULL_PROVIDER_OPS, nullptr, - nullptr}, - poolCreateExtParams{umfProxyPoolOps(), nullptr, nullptr, - &BA_GLOBAL_PROVIDER_OPS, nullptr, - nullptr})); + ::testing::Values( + poolCreateExtParams{&MALLOC_POOL_OPS, nullptr, nullptr, + &UMF_NULL_PROVIDER_OPS, nullptr, nullptr}, + poolCreateExtParams{umfProxyPoolOps(), nullptr, nullptr, + &BA_GLOBAL_PROVIDER_OPS, nullptr, nullptr}, + poolCreateExtParams{umfDisjointPoolOps(), defaultDisjointPoolConfig, + defaultDisjointPoolConfigDestroy, + &BA_GLOBAL_PROVIDER_OPS, nullptr, nullptr})); INSTANTIATE_TEST_SUITE_P(mallocMultiPoolTest, umfMultiPoolTest, ::testing::Values(poolCreateExtParams{ diff --git a/test/poolFixtures.hpp b/test/poolFixtures.hpp index d9a5410c0..6f18664f9 100644 --- a/test/poolFixtures.hpp +++ b/test/poolFixtures.hpp @@ -452,26 +452,45 @@ TEST_P(umfPoolTest, allocMaxSize) { } TEST_P(umfPoolTest, mallocUsableSize) { + [[maybe_unused]] auto pool_ops = std::get<0>(this->GetParam()); +#ifdef _WIN32 + if (pool_ops == &umf_test::MALLOC_POOL_OPS) { + GTEST_SKIP() + << "Windows Malloc Pool does not support umfPoolAlignedMalloc"; + } +#endif + if (!umf_test::isAlignedAllocSupported(pool.get())) { + GTEST_SKIP(); + } #ifdef __SANITIZE_ADDRESS__ - // Sanitizer replaces malloc_usable_size implementation with its own - GTEST_SKIP() - << "This test is invalid with AddressSanitizer instrumentation"; -#else + if (pool_ops == &umf_test::MALLOC_POOL_OPS) { + // Sanitizer replaces malloc_usable_size implementation with its own + GTEST_SKIP() + << "This test is invalid with AddressSanitizer instrumentation"; + } +#endif + for (size_t allocSize : + {32, 64, 1 << 6, 1 << 10, 1 << 13, 1 << 16, 1 << 19}) { + for (size_t alignment : {0, 1 << 6, 1 << 8, 1 << 12}) { + if (alignment >= allocSize) { + continue; + } + void *ptr = nullptr; + if (alignment == 0) { + ptr = umfPoolMalloc(pool.get(), allocSize); + } else { + ptr = umfPoolAlignedMalloc(pool.get(), allocSize, alignment); + } + ASSERT_NE(ptr, nullptr); + size_t result = umfPoolMallocUsableSize(pool.get(), ptr); + ASSERT_TRUE(result == 0 || result >= allocSize); - for (size_t allocSize : {32, 48, 1024, 8192}) { - char *ptr = static_cast(umfPoolMalloc(pool.get(), allocSize)); - ASSERT_NE(ptr, nullptr); - size_t result = umfPoolMallocUsableSize(pool.get(), ptr); - ASSERT_TRUE(result == 0 || result >= allocSize); + // Make sure we can write to this memory + memset(ptr, 123, result); - // Make sure we can write to this memory - for (size_t i = 0; i < result; i++) { - ptr[i] = 123; + umfPoolFree(pool.get(), ptr); } - - umfPoolFree(pool.get(), ptr); } -#endif } #endif /* UMF_TEST_POOL_FIXTURES_HPP */ diff --git a/test/pools/disjoint_pool.cpp b/test/pools/disjoint_pool.cpp index dad960187..02f769802 100644 --- a/test/pools/disjoint_pool.cpp +++ b/test/pools/disjoint_pool.cpp @@ -13,49 +13,6 @@ #include "provider_null.h" #include "provider_trace.h" -static constexpr size_t DEFAULT_DISJOINT_SLAB_MIN_SIZE = 4096; -static constexpr size_t DEFAULT_DISJOINT_MAX_POOLABLE_SIZE = 4096; -static constexpr size_t DEFAULT_DISJOINT_CAPACITY = 4; -static constexpr size_t DEFAULT_DISJOINT_MIN_BUCKET_SIZE = 64; - -void *defaultPoolConfig() { - umf_disjoint_pool_params_handle_t config = nullptr; - umf_result_t res = umfDisjointPoolParamsCreate(&config); - if (res != UMF_RESULT_SUCCESS) { - throw std::runtime_error("Failed to create pool params"); - } - res = umfDisjointPoolParamsSetSlabMinSize(config, - DEFAULT_DISJOINT_SLAB_MIN_SIZE); - if (res != UMF_RESULT_SUCCESS) { - umfDisjointPoolParamsDestroy(config); - throw std::runtime_error("Failed to set slab min size"); - } - res = umfDisjointPoolParamsSetMaxPoolableSize( - config, DEFAULT_DISJOINT_MAX_POOLABLE_SIZE); - if (res != UMF_RESULT_SUCCESS) { - umfDisjointPoolParamsDestroy(config); - throw std::runtime_error("Failed to set max poolable size"); - } - res = umfDisjointPoolParamsSetCapacity(config, DEFAULT_DISJOINT_CAPACITY); - if (res != UMF_RESULT_SUCCESS) { - umfDisjointPoolParamsDestroy(config); - throw std::runtime_error("Failed to set capacity"); - } - res = umfDisjointPoolParamsSetMinBucketSize( - config, DEFAULT_DISJOINT_MIN_BUCKET_SIZE); - if (res != UMF_RESULT_SUCCESS) { - umfDisjointPoolParamsDestroy(config); - throw std::runtime_error("Failed to set min bucket size"); - } - - return config; -} - -umf_result_t poolConfigDestroy(void *config) { - return umfDisjointPoolParamsDestroy( - static_cast(config)); -} - using umf_test::test; using namespace umf_test; @@ -92,7 +49,7 @@ TEST_F(test, internals) { provider_handle = providerUnique.get(); umf_disjoint_pool_params_handle_t params = - (umf_disjoint_pool_params_handle_t)defaultPoolConfig(); + (umf_disjoint_pool_params_handle_t)defaultDisjointPoolConfig(); // set to maximum tracing params->pool_trace = 3; params->max_poolable_size = 1024 * 1024; @@ -256,7 +213,7 @@ TEST_F(test, sharedLimits) { static constexpr size_t MaxSize = 4 * SlabMinSize; umf_disjoint_pool_params_handle_t params = - (umf_disjoint_pool_params_handle_t)defaultPoolConfig(); + (umf_disjoint_pool_params_handle_t)defaultDisjointPoolConfig(); umf_result_t ret = umfDisjointPoolParamsSetSlabMinSize(params, SlabMinSize); EXPECT_EQ(ret, UMF_RESULT_SUCCESS); @@ -373,22 +330,23 @@ TEST_F(test, disjointPoolInvalidBucketSize) { INSTANTIATE_TEST_SUITE_P(disjointPoolTests, umfPoolTest, ::testing::Values(poolCreateExtParams{ - umfDisjointPoolOps(), defaultPoolConfig, - poolConfigDestroy, &BA_GLOBAL_PROVIDER_OPS, - nullptr, nullptr})); + umfDisjointPoolOps(), defaultDisjointPoolConfig, + defaultDisjointPoolConfigDestroy, + &BA_GLOBAL_PROVIDER_OPS, nullptr, nullptr})); void *memProviderParams() { return (void *)&DEFAULT_DISJOINT_CAPACITY; } INSTANTIATE_TEST_SUITE_P( disjointPoolTests, umfMemTest, ::testing::Values(std::make_tuple( - poolCreateExtParams{umfDisjointPoolOps(), defaultPoolConfig, - poolConfigDestroy, &MOCK_OUT_OF_MEM_PROVIDER_OPS, - memProviderParams, nullptr}, + poolCreateExtParams{umfDisjointPoolOps(), defaultDisjointPoolConfig, + defaultDisjointPoolConfigDestroy, + &MOCK_OUT_OF_MEM_PROVIDER_OPS, memProviderParams, + nullptr}, static_cast(DEFAULT_DISJOINT_CAPACITY) / 2))); INSTANTIATE_TEST_SUITE_P(disjointMultiPoolTests, umfMultiPoolTest, ::testing::Values(poolCreateExtParams{ - umfDisjointPoolOps(), defaultPoolConfig, - poolConfigDestroy, &BA_GLOBAL_PROVIDER_OPS, - nullptr, nullptr})); + umfDisjointPoolOps(), defaultDisjointPoolConfig, + defaultDisjointPoolConfigDestroy, + &BA_GLOBAL_PROVIDER_OPS, nullptr, nullptr})); diff --git a/test/supp/drd-umf_test-provider_devdax_memory_ipc.supp b/test/supp/drd-umf_test-provider_devdax_memory_ipc.supp index cd44bb49a..025834658 100644 --- a/test/supp/drd-umf_test-provider_devdax_memory_ipc.supp +++ b/test/supp/drd-umf_test-provider_devdax_memory_ipc.supp @@ -6,3 +6,20 @@ fun:umfOpenIPCHandle ... } + +{ + False-positive ConflictingAccess in jemalloc + drd:ConflictingAccess + fun:atomic_* + ... + fun:je_* + ... +} + +{ + False-positive ConflictingAccess in tbbmalloc + drd:ConflictingAccess + ... + fun:tbb_pool_finalize + ... +} diff --git a/test/supp/drd-umf_test-provider_file_memory_ipc.supp b/test/supp/drd-umf_test-provider_file_memory_ipc.supp index 7fce24116..a15d860aa 100644 --- a/test/supp/drd-umf_test-provider_file_memory_ipc.supp +++ b/test/supp/drd-umf_test-provider_file_memory_ipc.supp @@ -14,3 +14,20 @@ fun:umfOpenIPCHandle ... } + +{ + False-positive ConflictingAccess in jemalloc + drd:ConflictingAccess + fun:atomic_* + ... + fun:je_* + ... +} + +{ + False-positive ConflictingAccess in tbbmalloc + drd:ConflictingAccess + ... + fun:tbb_pool_finalize + ... +} diff --git a/test/supp/drd-umf_test-provider_os_memory.supp b/test/supp/drd-umf_test-provider_os_memory.supp index cd44bb49a..025834658 100644 --- a/test/supp/drd-umf_test-provider_os_memory.supp +++ b/test/supp/drd-umf_test-provider_os_memory.supp @@ -6,3 +6,20 @@ fun:umfOpenIPCHandle ... } + +{ + False-positive ConflictingAccess in jemalloc + drd:ConflictingAccess + fun:atomic_* + ... + fun:je_* + ... +} + +{ + False-positive ConflictingAccess in tbbmalloc + drd:ConflictingAccess + ... + fun:tbb_pool_finalize + ... +} diff --git a/test/supp/helgrind-umf_test-provider_devdax_memory_ipc.supp b/test/supp/helgrind-umf_test-provider_devdax_memory_ipc.supp index 4fcd2786c..d6401e8ee 100644 --- a/test/supp/helgrind-umf_test-provider_devdax_memory_ipc.supp +++ b/test/supp/helgrind-umf_test-provider_devdax_memory_ipc.supp @@ -6,3 +6,20 @@ fun:umfOpenIPCHandle ... } + +{ + False-positive ConflictingAccess in jemalloc + Helgrind:Race + fun:atomic_* + ... + fun:je_* + ... +} + +{ + False-positive ConflictingAccess in tbbmalloc + Helgrind:Race + ... + fun:tbb_pool_finalize + ... +} diff --git a/test/supp/helgrind-umf_test-provider_file_memory_ipc.supp b/test/supp/helgrind-umf_test-provider_file_memory_ipc.supp index 4194f4847..cdc0bd8df 100644 --- a/test/supp/helgrind-umf_test-provider_file_memory_ipc.supp +++ b/test/supp/helgrind-umf_test-provider_file_memory_ipc.supp @@ -23,3 +23,20 @@ fun:critnib_find ... } + +{ + False-positive ConflictingAccess in jemalloc + Helgrind:Race + fun:atomic_* + ... + fun:je_* + ... +} + +{ + False-positive ConflictingAccess in tbbmalloc + Helgrind:Race + ... + fun:tbb_pool_finalize + ... +} diff --git a/test/supp/helgrind-umf_test-provider_os_memory.supp b/test/supp/helgrind-umf_test-provider_os_memory.supp index 4fcd2786c..d6401e8ee 100644 --- a/test/supp/helgrind-umf_test-provider_os_memory.supp +++ b/test/supp/helgrind-umf_test-provider_os_memory.supp @@ -6,3 +6,20 @@ fun:umfOpenIPCHandle ... } + +{ + False-positive ConflictingAccess in jemalloc + Helgrind:Race + fun:atomic_* + ... + fun:je_* + ... +} + +{ + False-positive ConflictingAccess in tbbmalloc + Helgrind:Race + ... + fun:tbb_pool_finalize + ... +} diff --git a/third_party/requirements.txt b/third_party/requirements.txt index 4b8244b3a..467ea1e03 100644 --- a/third_party/requirements.txt +++ b/third_party/requirements.txt @@ -12,7 +12,7 @@ sphinxcontrib_devhelp==2.0.0 sphinxcontrib_htmlhelp==2.1.0 sphinxcontrib_serializinghtml==2.0.0 sphinxcontrib_qthelp==2.0.0 -breathe==4.35.0 +breathe==4.36.0 sphinx==8.1.3 sphinx_book_theme==1.1.3 # Spelling check in documentation