diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 941c685e3..73b9b257a 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -86,6 +86,16 @@ function(add_umf_benchmark) set_property(TEST ${BENCH_NAME} PROPERTY ENVIRONMENT_MODIFICATION "${DLL_PATH_LIST}") endif() + if(LINUX) + # prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required + # because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests + # should use it instead of system one. + set_property( + TEST ${BENCH_NAME} + PROPERTY ENVIRONMENT_MODIFICATION + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib" + ) + endif() if(UMF_BUILD_LIBUMF_POOL_DISJOINT) target_compile_definitions(${BENCH_NAME} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 009f424ed..89f80ee2d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -72,6 +72,16 @@ if(UMF_BUILD_GPU_EXAMPLES set_property(TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION "${DLL_PATH_LIST}") endif() + if(LINUX) + # prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required + # because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests + # should use it instead of system one. + set_property( + TEST ${EXAMPLE_NAME} + PROPERTY ENVIRONMENT_MODIFICATION + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib" + ) + endif() else() message(STATUS "GPU Level Zero shared memory example requires " "UMF_BUILD_GPU_EXAMPLES, UMF_BUILD_LEVEL_ZERO_PROVIDER and " @@ -151,6 +161,16 @@ if(UMF_BUILD_GPU_EXAMPLES set_property(TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION "${DLL_PATH_LIST}") endif() + if(LINUX) + # prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required + # because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests + # should use it instead of system one. + set_property( + TEST ${EXAMPLE_NAME} + PROPERTY ENVIRONMENT_MODIFICATION + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib" + ) + endif() else() message( STATUS diff --git a/examples/ipc_level_zero/CMakeLists.txt b/examples/ipc_level_zero/CMakeLists.txt index 5c17d4c9c..273a88bb0 100644 --- a/examples/ipc_level_zero/CMakeLists.txt +++ b/examples/ipc_level_zero/CMakeLists.txt @@ -1,4 +1,4 @@ -# 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 @@ -69,6 +69,6 @@ if(LINUX) TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION - "LD_LIBRARY_PATH=path_list_append:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}" + "LD_LIBRARY_PATH=path_list_prepend:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}" ) endif() diff --git a/examples/level_zero_shared_memory/CMakeLists.txt b/examples/level_zero_shared_memory/CMakeLists.txt index 3711b4094..d05072ca2 100644 --- a/examples/level_zero_shared_memory/CMakeLists.txt +++ b/examples/level_zero_shared_memory/CMakeLists.txt @@ -1,4 +1,4 @@ -# 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 @@ -70,6 +70,6 @@ if(LINUX) TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION - "LD_LIBRARY_PATH=path_list_append:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}" + "LD_LIBRARY_PATH=path_list_prepend:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}" ) endif() diff --git a/include/umf/base.h b/include/umf/base.h index 32d84771f..8dad184f2 100644 --- a/include/umf/base.h +++ b/include/umf/base.h @@ -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 @@ -45,6 +45,8 @@ typedef enum umf_result_t { UMF_RESULT_ERROR_NOT_SUPPORTED = 5, ///< Operation not supported UMF_RESULT_ERROR_USER_SPECIFIC = 6, ///< Failure in user provider code (i.e in user provided callback) + UMF_RESULT_ERROR_DEPENDENCY_UNAVAILABLE = + 7, ///< External required dependency is unavailable or missing UMF_RESULT_ERROR_UNKNOWN = 0x7ffffffe ///< Unknown or internal error } umf_result_t; diff --git a/src/libumf.c b/src/libumf.c index b89e5c844..64314f4d3 100644 --- a/src/libumf.c +++ b/src/libumf.c @@ -1,6 +1,6 @@ /* * - * 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 @@ -12,6 +12,8 @@ #include "base_alloc_global.h" #include "ipc_cache.h" #include "memspace_internal.h" +#include "provider_cuda_internal.h" +#include "provider_level_zero_internal.h" #include "provider_tracking.h" #include "utils_common.h" #include "utils_log.h" @@ -79,6 +81,8 @@ void umfTearDown(void) { LOG_DEBUG("UMF base allocator destroyed"); fini_umfTearDown: + fini_ze_global_state(); + fini_cu_global_state(); LOG_DEBUG("UMF library finalized"); } } diff --git a/src/provider/provider_cuda.c b/src/provider/provider_cuda.c index a0f963fdd..c7929cc7e 100644 --- a/src/provider/provider_cuda.c +++ b/src/provider/provider_cuda.c @@ -12,8 +12,19 @@ #include #include +#include "provider_cuda_internal.h" +#include "utils_load_library.h" #include "utils_log.h" +static void *cu_lib_handle = NULL; + +void fini_cu_global_state(void) { + if (cu_lib_handle) { + utils_close_library(cu_lib_handle); + cu_lib_handle = NULL; + } +} + #if defined(UMF_NO_CUDA_PROVIDER) umf_result_t umfCUDAMemoryProviderParamsCreate( @@ -88,7 +99,6 @@ umf_memory_provider_ops_t *umfCUDAMemoryProviderOps(void) { #include "utils_assert.h" #include "utils_common.h" #include "utils_concurrency.h" -#include "utils_load_library.h" #include "utils_log.h" #include "utils_sanitizers.h" @@ -180,37 +190,45 @@ static void init_cu_global_state(void) { #else const char *lib_name = "libcuda.so"; #endif - // check if CUDA shared library is already loaded - // we pass 0 as a handle to search the global symbol table + // The CUDA shared library should be already loaded by the user + // of the CUDA provider. UMF just want to reuse it + // and increase the reference count to the CUDA shared library. + void *lib_handle = + utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_NO_LOAD); + if (!lib_handle) { + LOG_ERR("Failed to open CUDA shared library"); + Init_cu_global_state_failed = true; + return; + } // NOTE: some symbols defined in the lib have _vX postfixes - it is // important to load the proper version of functions - *(void **)&g_cu_ops.cuMemGetAllocationGranularity = - utils_get_symbol_addr(0, "cuMemGetAllocationGranularity", lib_name); + *(void **)&g_cu_ops.cuMemGetAllocationGranularity = utils_get_symbol_addr( + lib_handle, "cuMemGetAllocationGranularity", lib_name); *(void **)&g_cu_ops.cuMemAlloc = - utils_get_symbol_addr(0, "cuMemAlloc_v2", lib_name); + utils_get_symbol_addr(lib_handle, "cuMemAlloc_v2", lib_name); *(void **)&g_cu_ops.cuMemHostAlloc = - utils_get_symbol_addr(0, "cuMemHostAlloc", lib_name); + utils_get_symbol_addr(lib_handle, "cuMemHostAlloc", lib_name); *(void **)&g_cu_ops.cuMemAllocManaged = - utils_get_symbol_addr(0, "cuMemAllocManaged", lib_name); + utils_get_symbol_addr(lib_handle, "cuMemAllocManaged", lib_name); *(void **)&g_cu_ops.cuMemFree = - utils_get_symbol_addr(0, "cuMemFree_v2", lib_name); + utils_get_symbol_addr(lib_handle, "cuMemFree_v2", lib_name); *(void **)&g_cu_ops.cuMemFreeHost = - utils_get_symbol_addr(0, "cuMemFreeHost", lib_name); + utils_get_symbol_addr(lib_handle, "cuMemFreeHost", lib_name); *(void **)&g_cu_ops.cuGetErrorName = - utils_get_symbol_addr(0, "cuGetErrorName", lib_name); + utils_get_symbol_addr(lib_handle, "cuGetErrorName", lib_name); *(void **)&g_cu_ops.cuGetErrorString = - utils_get_symbol_addr(0, "cuGetErrorString", lib_name); + utils_get_symbol_addr(lib_handle, "cuGetErrorString", lib_name); *(void **)&g_cu_ops.cuCtxGetCurrent = - utils_get_symbol_addr(0, "cuCtxGetCurrent", lib_name); + utils_get_symbol_addr(lib_handle, "cuCtxGetCurrent", lib_name); *(void **)&g_cu_ops.cuCtxSetCurrent = - utils_get_symbol_addr(0, "cuCtxSetCurrent", lib_name); + utils_get_symbol_addr(lib_handle, "cuCtxSetCurrent", lib_name); *(void **)&g_cu_ops.cuIpcGetMemHandle = - utils_get_symbol_addr(0, "cuIpcGetMemHandle", lib_name); + utils_get_symbol_addr(lib_handle, "cuIpcGetMemHandle", lib_name); *(void **)&g_cu_ops.cuIpcOpenMemHandle = - utils_get_symbol_addr(0, "cuIpcOpenMemHandle_v2", lib_name); + utils_get_symbol_addr(lib_handle, "cuIpcOpenMemHandle_v2", lib_name); *(void **)&g_cu_ops.cuIpcCloseMemHandle = - utils_get_symbol_addr(0, "cuIpcCloseMemHandle", lib_name); + utils_get_symbol_addr(lib_handle, "cuIpcCloseMemHandle", lib_name); if (!g_cu_ops.cuMemGetAllocationGranularity || !g_cu_ops.cuMemAlloc || !g_cu_ops.cuMemHostAlloc || !g_cu_ops.cuMemAllocManaged || @@ -221,7 +239,10 @@ static void init_cu_global_state(void) { !g_cu_ops.cuIpcCloseMemHandle) { LOG_FATAL("Required CUDA symbols not found."); Init_cu_global_state_failed = true; + utils_close_library(lib_handle); + return; } + cu_lib_handle = lib_handle; } umf_result_t umfCUDAMemoryProviderParamsCreate( @@ -327,7 +348,7 @@ static umf_result_t cu_memory_provider_initialize(void *params, utils_init_once(&cu_is_initialized, init_cu_global_state); if (Init_cu_global_state_failed) { LOG_FATAL("Loading CUDA symbols failed"); - return UMF_RESULT_ERROR_UNKNOWN; + return UMF_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; } cu_memory_provider_t *cu_provider = diff --git a/src/provider/provider_cuda_internal.h b/src/provider/provider_cuda_internal.h new file mode 100644 index 000000000..bc3d79d4a --- /dev/null +++ b/src/provider/provider_cuda_internal.h @@ -0,0 +1,10 @@ +/* + * + * Copyright (C) 2025 Intel Corporation + * + * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + */ + +void fini_cu_global_state(void); diff --git a/src/provider/provider_level_zero.c b/src/provider/provider_level_zero.c index 2d6aa074b..f89661401 100644 --- a/src/provider/provider_level_zero.c +++ b/src/provider/provider_level_zero.c @@ -14,8 +14,19 @@ #include #include +#include "provider_level_zero_internal.h" +#include "utils_load_library.h" #include "utils_log.h" +static void *ze_lib_handle = NULL; + +void fini_ze_global_state(void) { + if (ze_lib_handle) { + utils_close_library(ze_lib_handle); + ze_lib_handle = NULL; + } +} + #if defined(UMF_NO_LEVEL_ZERO_PROVIDER) umf_result_t umfLevelZeroMemoryProviderParamsCreate( @@ -105,7 +116,6 @@ umf_memory_provider_ops_t *umfLevelZeroMemoryProviderOps(void) { #include "utils_assert.h" #include "utils_common.h" #include "utils_concurrency.h" -#include "utils_load_library.h" #include "utils_log.h" #include "utils_sanitizers.h" #include "ze_api.h" @@ -207,32 +217,41 @@ static void init_ze_global_state(void) { #else const char *lib_name = "libze_loader.so"; #endif - // check if Level Zero shared library is already loaded - // we pass 0 as a handle to search the global symbol table + // The Level Zero shared library should be already loaded by the user + // of the Level Zero provider. UMF just want to reuse it + // and increase the reference count to the Level Zero shared library. + void *lib_handle = + utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_NO_LOAD); + if (!lib_handle) { + LOG_FATAL("Failed to open Level Zero shared library"); + Init_ze_global_state_failed = true; + return; + } + *(void **)&g_ze_ops.zeMemAllocHost = - utils_get_symbol_addr(0, "zeMemAllocHost", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemAllocHost", lib_name); *(void **)&g_ze_ops.zeMemAllocDevice = - utils_get_symbol_addr(0, "zeMemAllocDevice", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemAllocDevice", lib_name); *(void **)&g_ze_ops.zeMemAllocShared = - utils_get_symbol_addr(0, "zeMemAllocShared", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemAllocShared", lib_name); *(void **)&g_ze_ops.zeMemFree = - utils_get_symbol_addr(0, "zeMemFree", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemFree", lib_name); *(void **)&g_ze_ops.zeMemGetIpcHandle = - utils_get_symbol_addr(0, "zeMemGetIpcHandle", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemGetIpcHandle", lib_name); *(void **)&g_ze_ops.zeMemPutIpcHandle = - utils_get_symbol_addr(0, "zeMemPutIpcHandle", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemPutIpcHandle", lib_name); *(void **)&g_ze_ops.zeMemOpenIpcHandle = - utils_get_symbol_addr(0, "zeMemOpenIpcHandle", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemOpenIpcHandle", lib_name); *(void **)&g_ze_ops.zeMemCloseIpcHandle = - utils_get_symbol_addr(0, "zeMemCloseIpcHandle", lib_name); - *(void **)&g_ze_ops.zeContextMakeMemoryResident = - utils_get_symbol_addr(0, "zeContextMakeMemoryResident", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemCloseIpcHandle", lib_name); + *(void **)&g_ze_ops.zeContextMakeMemoryResident = utils_get_symbol_addr( + lib_handle, "zeContextMakeMemoryResident", lib_name); *(void **)&g_ze_ops.zeDeviceGetProperties = - utils_get_symbol_addr(0, "zeDeviceGetProperties", lib_name); + utils_get_symbol_addr(lib_handle, "zeDeviceGetProperties", lib_name); *(void **)&g_ze_ops.zeMemFreeExt = - utils_get_symbol_addr(0, "zeMemFreeExt", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemFreeExt", lib_name); *(void **)&g_ze_ops.zeMemGetAllocProperties = - utils_get_symbol_addr(0, "zeMemGetAllocProperties", lib_name); + utils_get_symbol_addr(lib_handle, "zeMemGetAllocProperties", lib_name); if (!g_ze_ops.zeMemAllocHost || !g_ze_ops.zeMemAllocDevice || !g_ze_ops.zeMemAllocShared || !g_ze_ops.zeMemFree || @@ -244,7 +263,10 @@ static void init_ze_global_state(void) { // starting from Level Zero 1.6 LOG_FATAL("Required Level Zero symbols not found."); Init_ze_global_state_failed = true; + utils_close_library(lib_handle); + return; } + ze_lib_handle = lib_handle; } umf_result_t umfLevelZeroMemoryProviderParamsCreate( @@ -551,7 +573,7 @@ static umf_result_t ze_memory_provider_initialize(void *params, utils_init_once(&ze_is_initialized, init_ze_global_state); if (Init_ze_global_state_failed) { LOG_FATAL("Loading Level Zero symbols failed"); - return UMF_RESULT_ERROR_UNKNOWN; + return UMF_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; } ze_memory_provider_t *ze_provider = diff --git a/src/provider/provider_level_zero_internal.h b/src/provider/provider_level_zero_internal.h new file mode 100644 index 000000000..7da299ffd --- /dev/null +++ b/src/provider/provider_level_zero_internal.h @@ -0,0 +1,10 @@ +/* + * + * Copyright (C) 2025 Intel Corporation + * + * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + */ + +void fini_ze_global_state(void); diff --git a/src/utils/utils_level_zero.cpp b/src/utils/utils_level_zero.cpp index 02e961d49..f5a42b0fa 100644 --- a/src/utils/utils_level_zero.cpp +++ b/src/utils/utils_level_zero.cpp @@ -144,10 +144,15 @@ int InitLevelZeroOps() { const char *lib_name = "libze_loader.so"; #endif // Load Level Zero symbols - // NOTE that we use UMF_UTIL_OPEN_LIBRARY_GLOBAL which add all loaded symbols to the +#if OPEN_ZE_LIBRARY_GLOBAL + // NOTE UMF_UTIL_OPEN_LIBRARY_GLOBAL adds all loaded symbols to the // global symbol table. + int open_flags = UMF_UTIL_OPEN_LIBRARY_GLOBAL; +#else + int open_flags = 0; +#endif zeDlHandle = std::unique_ptr( - utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_GLOBAL)); + utils_open_library(lib_name, open_flags)); *(void **)&libze_ops.zeInit = utils_get_symbol_addr(zeDlHandle.get(), "zeInit", lib_name); if (libze_ops.zeInit == nullptr) { diff --git a/src/utils/utils_load_library.c b/src/utils/utils_load_library.c index ef0da450b..d774fec84 100644 --- a/src/utils/utils_load_library.c +++ b/src/utils/utils_load_library.c @@ -1,6 +1,6 @@ /* * - * 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 @@ -32,7 +32,11 @@ #ifdef _WIN32 void *utils_open_library(const char *filename, int userFlags) { - (void)userFlags; //unused for win + if (userFlags & UMF_UTIL_OPEN_LIBRARY_NO_LOAD) { + HMODULE hModule; + BOOL ret = GetModuleHandleEx(0, TEXT(filename), &hModule); + return ret ? hModule : NULL; + } return LoadLibrary(TEXT(filename)); } @@ -66,6 +70,9 @@ void *utils_open_library(const char *filename, int userFlags) { if (userFlags & UMF_UTIL_OPEN_LIBRARY_GLOBAL) { dlopenFlags |= RTLD_GLOBAL; } + if (userFlags & UMF_UTIL_OPEN_LIBRARY_NO_LOAD) { + dlopenFlags |= RTLD_NOLOAD; + } void *handle = dlopen(filename, dlopenFlags); if (handle == NULL) { diff --git a/src/utils/utils_load_library.h b/src/utils/utils_load_library.h index 3206183f5..5b6e71239 100644 --- a/src/utils/utils_load_library.h +++ b/src/utils/utils_load_library.h @@ -1,6 +1,6 @@ /* * - * 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 @@ -17,7 +17,10 @@ #ifdef __cplusplus extern "C" { #endif +// The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries. #define UMF_UTIL_OPEN_LIBRARY_GLOBAL 1 +// Don't load the library. utils_open_library succeeds if the library is already loaded. +#define UMF_UTIL_OPEN_LIBRARY_NO_LOAD 1 << 1 void *utils_open_library(const char *filename, int userFlags); int utils_close_library(void *handle); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b841cceba..cdbe2425f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -154,6 +154,16 @@ function(add_umf_test) set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT_MODIFICATION "${DLL_PATH_LIST}") endif() + if(LINUX) + # prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required + # because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests + # should use it instead of system one. + set_property( + TEST ${TEST_NAME} + PROPERTY ENVIRONMENT_MODIFICATION + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib" + ) + endif() endfunction() add_subdirectory(common) @@ -405,12 +415,20 @@ if(UMF_BUILD_GPU_TESTS AND UMF_BUILD_LEVEL_ZERO_PROVIDER) LIBS ${UMF_UTILS_FOR_TEST} ze_loader) add_umf_test( - NAME provider_level_zero_dlopen + NAME provider_level_zero_dlopen_global SRCS providers/provider_level_zero.cpp ${UMF_UTILS_DIR}/utils_level_zero.cpp ${BA_SOURCES_FOR_TEST} LIBS ${UMF_UTILS_FOR_TEST}) - target_compile_definitions(umf_test-provider_level_zero_dlopen - PUBLIC USE_DLOPEN=1) + target_compile_definitions(umf_test-provider_level_zero_dlopen_global + PUBLIC USE_DLOPEN=1 OPEN_ZE_LIBRARY_GLOBAL=1) + + add_umf_test( + NAME provider_level_zero_dlopen_local + SRCS providers/provider_level_zero.cpp + ${UMF_UTILS_DIR}/utils_level_zero.cpp ${BA_SOURCES_FOR_TEST} + LIBS ${UMF_UTILS_FOR_TEST}) + target_compile_definitions(umf_test-provider_level_zero_dlopen_local + PUBLIC USE_DLOPEN=1 OPEN_ZE_LIBRARY_GLOBAL=0) endif() if(NOT UMF_BUILD_LEVEL_ZERO_PROVIDER) @@ -432,12 +450,20 @@ if(UMF_BUILD_GPU_TESTS AND UMF_BUILD_CUDA_PROVIDER) LIBS ${UMF_UTILS_FOR_TEST} cuda) add_umf_test( - NAME provider_cuda_dlopen + NAME provider_cuda_dlopen_global + SRCS providers/provider_cuda.cpp providers/cuda_helpers.cpp + ${BA_SOURCES_FOR_TEST} + LIBS ${UMF_UTILS_FOR_TEST}) + target_compile_definitions(umf_test-provider_cuda_dlopen_global + PUBLIC USE_DLOPEN=1 OPEN_CU_LIBRARY_GLOBAL=1) + + add_umf_test( + NAME provider_cuda_dlopen_local SRCS providers/provider_cuda.cpp providers/cuda_helpers.cpp ${BA_SOURCES_FOR_TEST} LIBS ${UMF_UTILS_FOR_TEST}) - target_compile_definitions(umf_test-provider_cuda_dlopen - PUBLIC USE_DLOPEN=1) + target_compile_definitions(umf_test-provider_cuda_dlopen_local + PUBLIC USE_DLOPEN=1 OPEN_CU_LIBRARY_GLOBAL=0) else() message( STATUS @@ -535,6 +561,16 @@ function(add_umf_ipc_test) if(NOT UMF_TESTS_FAIL_ON_SKIP) set_tests_properties(${TEST_NAME} PROPERTIES SKIP_RETURN_CODE 125) endif() + if(LINUX) + # prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required + # because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests + # should use it instead of system one. + set_property( + TEST ${TEST_NAME} + PROPERTY ENVIRONMENT_MODIFICATION + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib" + ) + endif() endfunction() if(LINUX) @@ -740,5 +776,15 @@ if(LINUX "${CMAKE_INSTALL_PREFIX}" "${STANDALONE_CMAKE_OPTIONS}" ${EXAMPLES} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + if(LINUX) + # prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is + # required because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so + # and tests should use it instead of system one. + set_property( + TEST umf-standalone_examples + PROPERTY + ENVIRONMENT_MODIFICATION + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib") + endif() endif() endif() diff --git a/test/providers/cuda_helpers.cpp b/test/providers/cuda_helpers.cpp index aa0647080..a607d7ecb 100644 --- a/test/providers/cuda_helpers.cpp +++ b/test/providers/cuda_helpers.cpp @@ -113,10 +113,15 @@ int InitCUDAOps() { const char *lib_name = "libcuda.so"; #endif // CUDA symbols - // NOTE that we use UMF_UTIL_OPEN_LIBRARY_GLOBAL which add all loaded - // symbols to the global symbol table. +#if OPEN_CU_LIBRARY_GLOBAL + // NOTE UMF_UTIL_OPEN_LIBRARY_GLOBAL adds all loaded symbols to the + // global symbol table. + int open_flags = UMF_UTIL_OPEN_LIBRARY_GLOBAL; +#else + int open_flags = 0; +#endif cuDlHandle = std::unique_ptr( - utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_GLOBAL)); + utils_open_library(lib_name, open_flags)); // NOTE: some symbols defined in the lib have _vX postfixes - this is // important to load the proper version of functions