diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1317482fd..f209cf2c5 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -12,6 +12,7 @@ permissions: env: BUILD_DIR : "${{github.workspace}}/build" + INSTALL_DIR: "${{github.workspace}}/build/install" jobs: fuzz-test: @@ -95,14 +96,14 @@ jobs: name: Windows ${{matrix.generator}} generator strategy: matrix: - os: ['windows-2019', 'windows-2022'] - build_type: [Release] + build_type: [Debug, Release] compiler: [{c: cl, cxx: cl}] shared_library: ['ON', 'OFF'] static_hwloc: ['ON', 'OFF'] generator: ['Ninja', 'NMake Makefiles'] + umfd_lib: ['ON', 'OFF'] - runs-on: ${{matrix.os}} + runs-on: windows-latest steps: - name: Checkout @@ -112,23 +113,23 @@ jobs: - name: Set VCPKG_PATH with hwloc if: matrix.static_hwloc == 'OFF' - run: echo "VCPKG_PATH='${{github.workspace}}/build/vcpkg/packages/hwloc_x64-windows;${{github.workspace}}/build/vcpkg/packages/tbb_x64-windows;${{github.workspace}}/build/vcpkg/packages/jemalloc_x64-windows'" >> $env:GITHUB_ENV + run: echo "VCPKG_PATH=${{github.workspace}}/build/vcpkg/packages/hwloc_x64-windows;${{github.workspace}}/build/vcpkg/packages/tbb_x64-windows;${{github.workspace}}/build/vcpkg/packages/jemalloc_x64-windows" >> $env:GITHUB_ENV - name: Set VCPKG_PATH without hwloc if: matrix.static_hwloc == 'ON' - run: echo "VCPKG_PATH='${{github.workspace}}/build/vcpkg/packages/tbb_x64-windows;${{github.workspace}}/build/vcpkg/packages/jemalloc_x64-windows'" >> $env:GITHUB_ENV + run: echo "VCPKG_PATH=${{github.workspace}}/build/vcpkg/packages/tbb_x64-windows;${{github.workspace}}/build/vcpkg/packages/jemalloc_x64-windows" >> $env:GITHUB_ENV - name: Initialize vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 env: VCPKG_PATH: ${{env.VCPKG_PATH}} with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies - run: vcpkg install + run: vcpkg install --triplet x64-windows - name: Install Ninja if: matrix.generator == 'Ninja' @@ -141,6 +142,7 @@ jobs: run: > cmake -B ${{env.BUILD_DIR}} + -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_PREFIX_PATH="${{env.VCPKG_PATH}}" -DCMAKE_C_COMPILER=${{matrix.compiler.c}} -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}} @@ -153,6 +155,7 @@ jobs: -DUMF_BUILD_LEVEL_ZERO_PROVIDER=ON -DUMF_BUILD_CUDA_PROVIDER=ON -DUMF_TESTS_FAIL_ON_SKIP=ON + ${{ matrix.umfd_lib == 'ON' && '-DUMF_USE_DEBUG_POSTFIX=ON' || '' }} - name: Build UMF shell: cmd @@ -163,6 +166,25 @@ jobs: working-directory: ${{env.BUILD_DIR}} run: ctest -C ${{matrix.build_type}} --output-on-failure --test-dir test + - name: Get UMF version + run: | + $version = (git describe --tags --abbrev=0 | Select-String -Pattern '\d+\.\d+\.\d+').Matches.Value + echo "UMF_VERSION=$version" >> $env:GITHUB_ENV + shell: pwsh + + - name: Test UMF installation and uninstallation + # The '--shared-library' parameter is added to the installation test when the UMF is built as a shared library + # The '--umfd-lib' parameter is added when the UMF is built with the umfd library + run: > + python3 ${{github.workspace}}/test/test_installation.py + --build-dir ${{env.BUILD_DIR}} + --install-dir ${{env.INSTALL_DIR}} + --build-type ${{matrix.build_type}} + --umf-version ${{env.UMF_VERSION}} + ${{ matrix.shared_library == 'ON' && '--proxy --shared-library' || '' }} + ${{ matrix.umfd_lib == 'ON' && '--umfd-lib' || ''}} + ${{ matrix.static_hwloc == 'ON' && '--hwloc' || '' }} + icx: name: ICX env: @@ -190,12 +212,12 @@ jobs: - name: Initialize vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies - run: vcpkg install + run: vcpkg install --triplet x64-windows - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@96bed6edff20d1dd61ecff9b75cc519d516e6401 # v5 diff --git a/.github/workflows/reusable_basic.yml b/.github/workflows/reusable_basic.yml index 41ce4b385..b30bfed4c 100644 --- a/.github/workflows/reusable_basic.yml +++ b/.github/workflows/reusable_basic.yml @@ -241,6 +241,7 @@ jobs: shared_library: 'ON' level_zero_provider: 'ON' cuda_provider: 'ON' + umfd_lib: 'ON' - os: 'windows-2022' build_type: Release compiler: {c: cl, cxx: cl} @@ -259,12 +260,12 @@ jobs: - name: Initialize vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies - run: vcpkg install + run: vcpkg install --triplet x64-windows shell: pwsh # Specifies PowerShell as the shell for running the script. - name: Get UMF version @@ -289,6 +290,7 @@ jobs: -DUMF_BUILD_LEVEL_ZERO_PROVIDER=${{matrix.level_zero_provider}} -DUMF_BUILD_CUDA_PROVIDER=${{matrix.cuda_provider}} -DUMF_TESTS_FAIL_ON_SKIP=ON + -DUMF_USE_DEBUG_POSTFIX=${{matrix.umfd_lib}} - name: Build UMF run: cmake --build ${{env.BUILD_DIR}} --config ${{matrix.build_type}} -j $Env:NUMBER_OF_PROCESSORS @@ -307,6 +309,7 @@ jobs: ${{matrix.shared_library == 'ON' && '--proxy' || '' }} --umf-version ${{env.UMF_VERSION}} ${{ matrix.shared_library == 'ON' && '--shared-library' || ''}} + ${{ matrix.umfd_lib == 'ON' && '--umfd-lib' || ''}} - name: check /DEPENDENTLOADFLAG in umf.dll if: ${{matrix.shared_library == 'ON' && matrix.compiler.cxx == 'cl'}} diff --git a/.github/workflows/reusable_codeql.yml b/.github/workflows/reusable_codeql.yml index 046c32081..252e70eee 100644 --- a/.github/workflows/reusable_codeql.yml +++ b/.github/workflows/reusable_codeql.yml @@ -48,14 +48,14 @@ jobs: if: matrix.os == 'windows-latest' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: "[Win] Install dependencies" if: matrix.os == 'windows-latest' run: | - vcpkg install + vcpkg install --triplet x64-windows python3 -m pip install -r third_party/requirements.txt - name: "[Lin] Install apt packages" diff --git a/.github/workflows/reusable_compatibility.yml b/.github/workflows/reusable_compatibility.yml index 5116a59f4..523b09e12 100644 --- a/.github/workflows/reusable_compatibility.yml +++ b/.github/workflows/reusable_compatibility.yml @@ -118,14 +118,14 @@ jobs: - name: Initialize vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{github.workspace}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' # NOTE we use vcpkg setup from "tag" version - name: Install dependencies working-directory: ${{github.workspace}}/tag_version - run: vcpkg install + run: vcpkg install --triplet x64-windows shell: pwsh # Specifies PowerShell as the shell for running the script. - name: Configure "tag" UMF build diff --git a/.github/workflows/reusable_fast.yml b/.github/workflows/reusable_fast.yml index 90a8f023f..7b1087ed0 100644 --- a/.github/workflows/reusable_fast.yml +++ b/.github/workflows/reusable_fast.yml @@ -60,13 +60,13 @@ jobs: if: matrix.os == 'windows-latest' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies (windows-latest) if: matrix.os == 'windows-latest' - run: vcpkg install + run: vcpkg install --triplet x64-windows shell: pwsh # Specifies PowerShell as the shell for running the script. - name: Install dependencies diff --git a/.github/workflows/reusable_gpu.yml b/.github/workflows/reusable_gpu.yml index 721d85206..6fcd40820 100644 --- a/.github/workflows/reusable_gpu.yml +++ b/.github/workflows/reusable_gpu.yml @@ -68,13 +68,13 @@ jobs: if: matrix.os == 'Windows' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: "[Win] Install dependencies" if: matrix.os == 'Windows' - run: vcpkg install + run: vcpkg install --triplet x64-windows # note: disable all providers except the one being tested # '-DCMAKE_SUPPRESS_REGENERATION=ON' is the WA for the error: "CUSTOMBUILD : CMake error : Cannot restore timestamp" diff --git a/.github/workflows/reusable_sanitizers.yml b/.github/workflows/reusable_sanitizers.yml index 1a044308e..c74448e1d 100644 --- a/.github/workflows/reusable_sanitizers.yml +++ b/.github/workflows/reusable_sanitizers.yml @@ -106,12 +106,12 @@ jobs: - name: Initialize vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: - vcpkgGitCommitId: 3dd44b931481d7a8e9ba412621fa810232b66289 + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies - run: vcpkg install + run: vcpkg install --triplet x64-windows shell: pwsh # Specifies PowerShell as the shell for running the script. # TODO enable level zero provider diff --git a/CMakeLists.txt b/CMakeLists.txt index 146869a82..f7e640abc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,8 @@ macro(umf_option) option(${ARGV}) endmacro() +# All CMake options have to be explicitly set in the build_umfd target's +# configuration command umf_option(UMF_BUILD_SHARED_LIBRARY "Build UMF as shared library" OFF) umf_option(UMF_BUILD_LEVEL_ZERO_PROVIDER "Build Level Zero memory provider" ON) umf_option(UMF_BUILD_CUDA_PROVIDER "Build CUDA memory provider" ON) @@ -89,6 +91,8 @@ set(UMF_INSTALL_RPATH "Set the runtime search path to the directory with dependencies (e.g. hwloc)" ) +umf_option(UMF_USE_DEBUG_POSTFIX "Add a 'd' postfix to Windows debug libraries" + OFF) umf_option(UMF_DEVELOPER_MODE "Enable additional developer checks" OFF) umf_option( UMF_FORMAT_CODE_STYLE @@ -146,6 +150,8 @@ if(UMF_DEVELOPER_MODE) UMF_DEVELOPER_MODE=1) endif() +message(STATUS "CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}") + if(NOT UMF_BUILD_LIBUMF_POOL_JEMALLOC) set(UMF_POOL_JEMALLOC_ENABLED FALSE) set(JEMALLOC_FOUND FALSE) @@ -291,6 +297,7 @@ else() set(HWLOC_ENABLE_TESTING OFF) set(HWLOC_SKIP_LSTOPO ON) set(HWLOC_SKIP_TOOLS ON) + set(HWLOC_SKIP_INCLUDES ON) FetchContent_Declare( hwloc_targ @@ -434,6 +441,74 @@ elseif(UMF_BUILD_CUDA_PROVIDER) message(STATUS "CUDA_INCLUDE_DIRS = ${CUDA_INCLUDE_DIRS}") endif() +# Build the umfd target in a separate directory with Debug configuration +if(WINDOWS AND UMF_USE_DEBUG_POSTFIX) + # The build_umfd target's configuration command requires to have + # CMAKE_PREFIX_PATH with semicolons escaped + string(JOIN "\;" UMFD_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}) + add_custom_target( + build_umfd ALL + COMMAND + ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" -S ${UMF_CMAKE_SOURCE_DIR} + -B ${CMAKE_BINARY_DIR}/umfd_build -DCMAKE_BUILD_TYPE=Debug + -DCMAKE_DEBUG_POSTFIX=d + -DCMAKE_PREFIX_PATH="${UMFD_CMAKE_PREFIX_PATH}" + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DUMF_USE_DEBUG_POSTFIX=OFF + -DUMF_BUILD_SHARED_LIBRARY=${UMF_BUILD_SHARED_LIBRARY} + -DUMF_BUILD_LEVEL_ZERO_PROVIDER=${UMF_BUILD_LEVEL_ZERO_PROVIDER} + -DUMF_BUILD_CUDA_PROVIDER=${UMF_BUILD_CUDA_PROVIDER} + -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=${UMF_BUILD_LIBUMF_POOL_JEMALLOC} + -DUMF_BUILD_TESTS=OFF -DUMF_BUILD_GPU_TESTS=OFF + -DUMF_BUILD_BENCHMARKS=OFF -DUMF_BUILD_BENCHMARKS_MT=OFF + -DUMF_BUILD_EXAMPLES=OFF -DUMF_BUILD_GPU_EXAMPLES=OFF + -DUMF_BUILD_FUZZTESTS=OFF -DUMF_DISABLE_HWLOC=${UMF_DISABLE_HWLOC} + -DUMF_LINK_HWLOC_STATICALLY=${UMF_LINK_HWLOC_STATICALLY} + -DUMF_HWLOC_NAME=${UMF_HWLOC_NAME} + -DUMF_INSTALL_RPATH=${UMF_INSTALL_RPATH} -DUMF_DEVELOPER_MODE=OFF + -DUMF_FORMAT_CODE_STYLE=OFF -DUMF_TESTS_FAIL_ON_SKIP=OFF + -DUMF_USE_ASAN=OFF -DUMF_USE_UBSAN=OFF -DUMF_USE_TSAN=OFF + -DUMF_USE_MSAN=OFF -DUMF_USE_VALGRIND=OFF -DUMF_USE_COVERAGE=OFF + -DUMF_PROXY_LIB_BASED_ON_POOL=${UMF_PROXY_LIB_BASED_ON_POOL} + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/umfd_build --target + umf --config Debug + COMMENT + "Configuring and building umfd.dll in a separate directory with Debug configuration" + ) + + # Copy built UMF libraries to the main binary directory and remove + # umfd_build + if(CMAKE_CONFIGURATION_TYPES) + # Multi-config generator (e.g., Visual Studio) + set(UMFD_DLL_SRC "${CMAKE_BINARY_DIR}/umfd_build/bin/Debug/umfd.dll") + set(UMFD_LIB_SRC "${CMAKE_BINARY_DIR}/umfd_build/lib/Debug/umfd.lib") + set(UMFD_DLL "${CMAKE_BINARY_DIR}/bin/$/umfd.dll") + set(UMFD_LIB "${CMAKE_BINARY_DIR}/lib/$/umfd.lib") + else() + # Single-config generator (e.g., Ninja) + set(UMFD_DLL_SRC "${CMAKE_BINARY_DIR}/umfd_build/bin/umfd.dll") + set(UMFD_LIB_SRC "${CMAKE_BINARY_DIR}/umfd_build/lib/umfd.lib") + set(UMFD_DLL "${CMAKE_BINARY_DIR}/bin/umfd.dll") + set(UMFD_LIB "${CMAKE_BINARY_DIR}/lib/umfd.lib") + endif() + + if(UMF_BUILD_SHARED_LIBRARY) + add_custom_command( + TARGET build_umfd + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${UMFD_DLL_SRC} + ${UMFD_DLL} + COMMENT "Copying umfd.dll to the main binary directory") + endif() + add_custom_command( + TARGET build_umfd + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${UMFD_LIB_SRC} + ${UMFD_LIB} + COMMAND ${CMAKE_COMMAND} -E remove_directory + ${CMAKE_BINARY_DIR}/umfd_build DEPENDS ${UMFD_DLL} + COMMENT "Copying umfd.lib to the main library directory") +endif() + # This build type check is not possible on Windows when CMAKE_BUILD_TYPE is not # set, because in this case the build type is determined after a CMake # configuration is done (at the build time) @@ -826,6 +901,20 @@ endif() # --------------------------------------------------------------------------- # # Configure make install/uninstall and packages # --------------------------------------------------------------------------- # +# Install the umfd library files as part of the umfd component +if(WINDOWS AND UMF_USE_DEBUG_POSTFIX) + if(UMF_BUILD_SHARED_LIBRARY) + install( + FILES ${UMFD_DLL} + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT umfd) + endif() + install( + FILES ${UMFD_LIB} + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT umfd) +endif() + install(FILES ${PROJECT_SOURCE_DIR}/LICENSE.TXT DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}/") install( diff --git a/src/critnib/critnib.c b/src/critnib/critnib.c index 5625781d3..7db9dd3dc 100644 --- a/src/critnib/critnib.c +++ b/src/critnib/critnib.c @@ -246,8 +246,8 @@ static void free_node(struct critnib *__restrict c, } ASSERT(!is_leaf(n)); - n->child[0] = c->deleted_node; - c->deleted_node = n; + utils_atomic_store_release_ptr((void **)&n->child[0], c->deleted_node); + utils_atomic_store_release_ptr((void **)&c->deleted_node, n); } /* @@ -277,8 +277,8 @@ static void free_leaf(struct critnib *__restrict c, return; } - k->value = c->deleted_leaf; - c->deleted_leaf = k; + utils_atomic_store_release_ptr((void **)&k->value, c->deleted_leaf); + utils_atomic_store_release_ptr((void **)&c->deleted_leaf, k); } /* @@ -319,8 +319,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) { utils_annotate_memory_no_check(k, sizeof(struct critnib_leaf)); - k->key = key; - k->value = value; + utils_atomic_store_release_ptr((void **)&k->key, (void *)key); + utils_atomic_store_release_ptr((void **)&k->value, value); struct critnib_node *kn = (void *)((word)k | 1); @@ -358,7 +358,7 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) { free_leaf(c, to_leaf(kn)); if (update) { - to_leaf(n)->value = value; + utils_atomic_store_release_ptr(&to_leaf(n)->value, value); utils_mutex_unlock(&c->mutex); return 0; } else { @@ -381,13 +381,14 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) { utils_annotate_memory_no_check(m, sizeof(struct critnib_node)); for (int i = 0; i < SLNODES; i++) { - m->child[i] = NULL; + utils_atomic_store_release_ptr((void *)&m->child[i], NULL); } - m->child[slice_index(key, sh)] = kn; - m->child[slice_index(path, sh)] = n; + utils_atomic_store_release_ptr((void *)&m->child[slice_index(key, sh)], kn); + utils_atomic_store_release_ptr((void *)&m->child[slice_index(path, sh)], n); m->shift = sh; - m->path = key & path_mask(sh); + utils_atomic_store_release_u64((void *)&m->path, key & path_mask(sh)); + utils_atomic_store_release_ptr((void **)parent, m); utils_mutex_unlock(&c->mutex); @@ -569,12 +570,15 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n, * that shift points at the nib's lower rather than upper edge, so it * needs to be masked away as well. */ - if ((key ^ n->path) >> (n->shift) & ~NIB) { + word path; + sh_t shift = n->shift; + utils_atomic_load_acquire_u64((uint64_t *)&n->path, (uint64_t *)&path); + if ((key ^ path) >> (shift) & ~NIB) { /* * subtree is too far to the left? * -> its rightmost value is good */ - if (n->path < key) { + if (path < key) { return find_predecessor(n); } @@ -759,8 +763,9 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir, k = (n && kk->key == key) ? kk : NULL; } if (k) { - _rkey = k->key; - _rvalue = k->value; + utils_atomic_load_acquire_u64((uint64_t *)&k->key, + (uint64_t *)&_rkey); + utils_atomic_load_acquire_ptr(&k->value, (void **)&_rvalue); } utils_atomic_load_acquire_u64(&c->remove_count, &wrs2); } while (wrs1 + DELETED_LIFE <= wrs2); diff --git a/src/provider/provider_file_memory.c b/src/provider/provider_file_memory.c index 5cc377f32..12a923322 100644 --- a/src/provider/provider_file_memory.c +++ b/src/provider/provider_file_memory.c @@ -429,6 +429,8 @@ static umf_result_t file_alloc_aligned(file_memory_provider_t *file_provider, return UMF_RESULT_ERROR_UNKNOWN; } + assert(file_provider->offset_mmap <= file_provider->size_mmap); + if (file_provider->size_mmap - file_provider->offset_mmap < size) { umf_result = file_mmap_aligned(file_provider, size, alignment); if (umf_result != UMF_RESULT_SUCCESS) { @@ -454,7 +456,8 @@ static umf_result_t file_alloc_aligned(file_memory_provider_t *file_provider, size_t new_offset_fd = file_provider->offset_fd + new_offset_mmap - file_provider->offset_mmap; - if (file_provider->size_mmap - new_offset_mmap < size) { + // new_offset_mmap can be greater than file_provider->size_mmap + if (file_provider->size_mmap < size + new_offset_mmap) { umf_result = file_mmap_aligned(file_provider, size, alignment); if (umf_result != UMF_RESULT_SUCCESS) { utils_mutex_unlock(&file_provider->lock); diff --git a/src/provider/provider_level_zero.c b/src/provider/provider_level_zero.c index a4c68b391..af81e84bc 100644 --- a/src/provider/provider_level_zero.c +++ b/src/provider/provider_level_zero.c @@ -629,7 +629,7 @@ static umf_result_t ze_memory_provider_initialize(void *params, umf_result_t result = query_min_page_size(ze_provider, &ze_provider->min_page_size); if (result != UMF_RESULT_SUCCESS) { - ze_memory_provider_finalize(provider); + ze_memory_provider_finalize(ze_provider); return result; } diff --git a/test/poolFixtures.hpp b/test/poolFixtures.hpp index de5a54685..5f39e021d 100644 --- a/test/poolFixtures.hpp +++ b/test/poolFixtures.hpp @@ -136,7 +136,8 @@ TEST_P(umfPoolTest, allocFree) { auto *ptr = umfPoolMalloc(pool.get(), allocSize); ASSERT_NE(ptr, nullptr); std::memset(ptr, 0, allocSize); - umfPoolFree(pool.get(), ptr); + umf_result_t umf_result = umfPoolFree(pool.get(), ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } TEST_P(umfPoolTest, allocFreeNonAlignedSizes) { @@ -144,10 +145,33 @@ TEST_P(umfPoolTest, allocFreeNonAlignedSizes) { auto *ptr = umfPoolMalloc(pool.get(), allocSize); ASSERT_NE(ptr, nullptr); std::memset(ptr, 0, allocSize); - umfPoolFree(pool.get(), ptr); + umf_result_t umf_result = umfPoolFree(pool.get(), ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } } +TEST_P(umfPoolTest, allocFreeAligned) { +// ::aligned_alloc(alignment=4096, size=1) does not work under sanitizers for unknown reason +#if defined(_WIN32) || defined(__SANITIZE_ADDRESS__) || \ + defined(__SANITIZE_THREAD__) + // TODO: implement support for windows + GTEST_SKIP(); +#else + if (!umf_test::isAlignedAllocSupported(pool.get())) { + GTEST_SKIP(); + } + + size_t alignment = 4 * 1024; // 4kB + void *ptr = umfPoolAlignedMalloc(pool.get(), 1, alignment); + ASSERT_NE(ptr, nullptr); + ASSERT_TRUE(reinterpret_cast(ptr) % alignment == 0); + *(reinterpret_cast(ptr)) = (unsigned char)0xFF; + + umf_result_t umf_result = umfPoolFree(pool.get(), ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); +#endif +} + TEST_P(umfPoolTest, reallocFree) { if (!umf_test::isReallocSupported(pool.get())) { GTEST_SKIP(); @@ -160,7 +184,8 @@ TEST_P(umfPoolTest, reallocFree) { auto *new_ptr = umfPoolRealloc(pool.get(), ptr, allocSize * multiplier); ASSERT_NE(new_ptr, nullptr); std::memset(new_ptr, 0, allocSize * multiplier); - umfPoolFree(pool.get(), new_ptr); + umf_result_t umf_result = umfPoolFree(pool.get(), new_ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } TEST_P(umfPoolTest, callocFree) { @@ -174,7 +199,8 @@ TEST_P(umfPoolTest, callocFree) { for (size_t i = 0; i < num; ++i) { ASSERT_EQ(((int *)ptr)[i], 0); } - umfPoolFree(pool.get(), ptr); + umf_result_t umf_result = umfPoolFree(pool.get(), ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } void pow2AlignedAllocHelper(umf_memory_pool_handle_t pool) { @@ -195,9 +221,31 @@ void pow2AlignedAllocHelper(umf_memory_pool_handle_t pool) { } for (auto &ptr : allocs) { - umfPoolFree(pool, ptr); + umf_result_t umf_result = umfPoolFree(pool, ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } } + +// ::aligned_alloc(alignment=4096, size=1) does not work under sanitizers for unknown reason +#if !defined(__SANITIZE_ADDRESS__) && !defined(__SANITIZE_THREAD__) + // the same for size = 1 + for (size_t alignment = 1; alignment <= maxAlignment; alignment <<= 1) { + std::vector allocs; + + for (size_t alloc = 0; alloc < numAllocs; alloc++) { + auto *ptr = umfPoolAlignedMalloc(pool, 1, alignment); + ASSERT_NE(ptr, nullptr); + ASSERT_TRUE(reinterpret_cast(ptr) % alignment == 0); + *(reinterpret_cast(ptr)) = (unsigned char)0xFF; + allocs.push_back(ptr); + } + + for (auto &ptr : allocs) { + umf_result_t umf_result = umfPoolFree(pool, ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + } + } +#endif } TEST_P(umfPoolTest, pow2AlignedAlloc) { @@ -227,7 +275,8 @@ TEST_P(umfPoolTest, multiThreadedMallocFree) { } for (auto allocation : allocations) { - umfPoolFree(inPool, allocation); + umf_result_t umf_result = umfPoolFree(inPool, allocation); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } }; @@ -280,7 +329,8 @@ TEST_P(umfPoolTest, multiThreadedReallocFree) { for (auto allocation : allocations) { auto *ptr = umfPoolRealloc(inPool, allocation, allocSize * multiplier); - umfPoolFree(inPool, ptr); + umf_result_t umf_result = umfPoolFree(inPool, ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } }; @@ -310,7 +360,8 @@ TEST_P(umfPoolTest, multiThreadedCallocFree) { } for (auto allocation : allocations) { - umfPoolFree(inPool, allocation); + umf_result_t umf_result = umfPoolFree(inPool, allocation); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } }; @@ -335,7 +386,8 @@ TEST_P(umfPoolTest, multiThreadedMallocFreeRandomSizes) { } for (auto allocation : allocations) { - umfPoolFree(inPool, allocation); + umf_result_t umf_result = umfPoolFree(inPool, allocation); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } }; @@ -375,7 +427,8 @@ TEST_P(umfMemTest, outOfMem) { ASSERT_NE(allocations.back(), nullptr); for (int i = 0; i < expectedRecycledPoolAllocs; i++) { - umfPoolFree(hPool, allocations.back()); + umf_result_t umf_result = umfPoolFree(hPool, allocations.back()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); allocations.pop_back(); } @@ -385,7 +438,8 @@ TEST_P(umfMemTest, outOfMem) { } for (auto allocation : allocations) { - umfPoolFree(hPool, allocation); + umf_result_t umf_result = umfPoolFree(hPool, allocation); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } } @@ -490,7 +544,8 @@ TEST_P(umfPoolTest, mallocUsableSize) { // Make sure we can write to this memory memset(ptr, 123, result); - umfPoolFree(pool.get(), ptr); + umf_result_t umf_result = umfPoolFree(pool.get(), ptr); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } } } diff --git a/test/test_installation.py b/test/test_installation.py index ef30ac759..4cf789000 100644 --- a/test/test_installation.py +++ b/test/test_installation.py @@ -28,7 +28,8 @@ class UmfInstaller: proxy (bool): Determines whether the proxy library should be built together with the UMF library pools (List[str]): A list of enabled pools during the UMF compilation umf_version (Version): UMF version currently being built and installed - match_list (List[str]): A list of relative paths of files that should be installed + umfd_lib (bool): Determines if the UMF was built with the umfd library + hwloc (bool): Determines if hwloc is installed and should be checked """ def __init__( @@ -41,6 +42,8 @@ def __init__( proxy: bool, pools: List[str], umf_version: Version, + umfd_lib: bool, + hwloc: bool, ): self.workspace_dir = workspace_dir self.build_dir = build_dir @@ -50,6 +53,8 @@ def __init__( self.proxy = proxy self.pools = pools self.umf_version = umf_version + self.umfd_lib = umfd_lib + self.hwloc = hwloc self.match_list = self._create_match_list() def _create_match_list(self) -> List[str]: @@ -78,6 +83,8 @@ def _create_match_list(self) -> List[str]: bin.append("bin") if self.shared_library: bin.append("bin/umf.dll") + if self.umfd_lib: + bin.append("bin/umfd.dll") if self.proxy: bin.append("bin/umf_proxy.dll") @@ -97,10 +104,15 @@ def _create_match_list(self) -> List[str]: f"lib/cmake/umf/umf-targets-{self.build_type}.cmake", "lib/cmake/umf/umf-targets.cmake", ] + for pool in self.pools: lib.append(f"lib/{lib_prefix}{pool}.{lib_ext_static}") + if platform.system() == "Windows" and self.hwloc: + lib.append(f"lib/{lib_prefix}hwloc.{lib_ext_static}") if self.shared_library: lib.append(f"lib/{lib_prefix}umf.{lib_ext_shared}") + if platform.system() == "Windows" and self.umfd_lib: + lib.append(f"lib/{lib_prefix}umfd.{lib_ext_shared}") if platform.system() == "Linux": lib.append( @@ -114,6 +126,8 @@ def _create_match_list(self) -> List[str]: lib.append(f"lib/{lib_prefix}umf.{self.umf_version}.{lib_ext_shared}") else: lib.append(f"lib/{lib_prefix}umf.{lib_ext_static}") + if self.umfd_lib and platform.system() == "Windows": + lib.append(f"lib/{lib_prefix}umfd.{lib_ext_static}") if self.proxy: lib.append(f"lib/{lib_prefix}umf_proxy.{lib_ext_shared}") @@ -127,7 +141,6 @@ def _create_match_list(self) -> List[str]: f"lib/{lib_prefix}umf_proxy.{self.umf_version.major}.{lib_ext_shared}" ) - share = [] share = [ "share", "share/doc", @@ -283,6 +296,16 @@ def parse_arguments(self) -> argparse.Namespace: action="store", help="Current version of the UMF, e.g. 1.0.0", ) + self.parser.add_argument( + "--umfd-lib", + action="store_true", + help="Add this argument if the UMF was built with the umfd library", + ) + self.parser.add_argument( + "--hwloc", + action="store_true", + help="Add this argument if hwloc is installed and should be checked", + ) return self.parser.parse_args() def run(self) -> None: @@ -306,6 +329,8 @@ def run(self) -> None: self.args.proxy, pools, umf_version, + self.args.umfd_lib, + self.args.hwloc, ) print("Installation test - BEGIN", flush=True)