Skip to content

Commit 5a515c5

Browse files
authored
Merge pull request #1086 from vinser52/svinogra_l0_linking
Increase refcount to ze_loader/CUDA libraries when Level Zero/CUDA providers are used
2 parents 1160a27 + 664484f commit 5a515c5

File tree

15 files changed

+220
-55
lines changed

15 files changed

+220
-55
lines changed

benchmark/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ function(add_umf_benchmark)
8686
set_property(TEST ${BENCH_NAME} PROPERTY ENVIRONMENT_MODIFICATION
8787
"${DLL_PATH_LIST}")
8888
endif()
89+
if(LINUX)
90+
# prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required
91+
# because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests
92+
# should use it instead of system one.
93+
set_property(
94+
TEST ${BENCH_NAME}
95+
PROPERTY ENVIRONMENT_MODIFICATION
96+
"LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib"
97+
)
98+
endif()
8999

90100
if(UMF_BUILD_LIBUMF_POOL_DISJOINT)
91101
target_compile_definitions(${BENCH_NAME}

examples/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ if(UMF_BUILD_GPU_EXAMPLES
7272
set_property(TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION
7373
"${DLL_PATH_LIST}")
7474
endif()
75+
if(LINUX)
76+
# prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required
77+
# because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests
78+
# should use it instead of system one.
79+
set_property(
80+
TEST ${EXAMPLE_NAME}
81+
PROPERTY ENVIRONMENT_MODIFICATION
82+
"LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib"
83+
)
84+
endif()
7585
else()
7686
message(STATUS "GPU Level Zero shared memory example requires "
7787
"UMF_BUILD_GPU_EXAMPLES, UMF_BUILD_LEVEL_ZERO_PROVIDER and "
@@ -151,6 +161,16 @@ if(UMF_BUILD_GPU_EXAMPLES
151161
set_property(TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION
152162
"${DLL_PATH_LIST}")
153163
endif()
164+
if(LINUX)
165+
# prepend LD_LIBRARY_PATH with ${CMAKE_BINARY_DIR}/lib it is required
166+
# because ${CMAKE_BINARY_DIR}/lib contains libze_loader.so and tests
167+
# should use it instead of system one.
168+
set_property(
169+
TEST ${EXAMPLE_NAME}
170+
PROPERTY ENVIRONMENT_MODIFICATION
171+
"LD_LIBRARY_PATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib"
172+
)
173+
endif()
154174
else()
155175
message(
156176
STATUS

examples/ipc_level_zero/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2024 Intel Corporation
1+
# Copyright (C) 2024-2025 Intel Corporation
22
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

@@ -69,6 +69,6 @@ if(LINUX)
6969
TEST ${EXAMPLE_NAME}
7070
PROPERTY
7171
ENVIRONMENT_MODIFICATION
72-
"LD_LIBRARY_PATH=path_list_append:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}"
72+
"LD_LIBRARY_PATH=path_list_prepend:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}"
7373
)
7474
endif()

examples/level_zero_shared_memory/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2024 Intel Corporation
1+
# Copyright (C) 2024-2025 Intel Corporation
22
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

@@ -70,6 +70,6 @@ if(LINUX)
7070
TEST ${EXAMPLE_NAME}
7171
PROPERTY
7272
ENVIRONMENT_MODIFICATION
73-
"LD_LIBRARY_PATH=path_list_append:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}"
73+
"LD_LIBRARY_PATH=path_list_prepend:${LIBUMF_LIBRARY_DIRS};LD_LIBRARY_PATH=path_list_append:${LIBHWLOC_LIBRARY_DIRS}"
7474
)
7575
endif()

include/umf/base.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023-2024 Intel Corporation
3+
* Copyright (C) 2023-2025 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -45,6 +45,8 @@ typedef enum umf_result_t {
4545
UMF_RESULT_ERROR_NOT_SUPPORTED = 5, ///< Operation not supported
4646
UMF_RESULT_ERROR_USER_SPECIFIC =
4747
6, ///< Failure in user provider code (i.e in user provided callback)
48+
UMF_RESULT_ERROR_DEPENDENCY_UNAVAILABLE =
49+
7, ///< External required dependency is unavailable or missing
4850
UMF_RESULT_ERROR_UNKNOWN = 0x7ffffffe ///< Unknown or internal error
4951
} umf_result_t;
5052

src/libumf.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2024 Intel Corporation
3+
* Copyright (C) 2024-2025 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -12,6 +12,8 @@
1212
#include "base_alloc_global.h"
1313
#include "ipc_cache.h"
1414
#include "memspace_internal.h"
15+
#include "provider_cuda_internal.h"
16+
#include "provider_level_zero_internal.h"
1517
#include "provider_tracking.h"
1618
#include "utils_common.h"
1719
#include "utils_log.h"
@@ -79,6 +81,8 @@ void umfTearDown(void) {
7981
LOG_DEBUG("UMF base allocator destroyed");
8082

8183
fini_umfTearDown:
84+
fini_ze_global_state();
85+
fini_cu_global_state();
8286
LOG_DEBUG("UMF library finalized");
8387
}
8488
}

src/provider/provider_cuda.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,19 @@
1212
#include <umf.h>
1313
#include <umf/providers/provider_cuda.h>
1414

15+
#include "provider_cuda_internal.h"
16+
#include "utils_load_library.h"
1517
#include "utils_log.h"
1618

19+
static void *cu_lib_handle = NULL;
20+
21+
void fini_cu_global_state(void) {
22+
if (cu_lib_handle) {
23+
utils_close_library(cu_lib_handle);
24+
cu_lib_handle = NULL;
25+
}
26+
}
27+
1728
#if defined(UMF_NO_CUDA_PROVIDER)
1829

1930
umf_result_t umfCUDAMemoryProviderParamsCreate(
@@ -88,7 +99,6 @@ umf_memory_provider_ops_t *umfCUDAMemoryProviderOps(void) {
8899
#include "utils_assert.h"
89100
#include "utils_common.h"
90101
#include "utils_concurrency.h"
91-
#include "utils_load_library.h"
92102
#include "utils_log.h"
93103
#include "utils_sanitizers.h"
94104

@@ -180,37 +190,45 @@ static void init_cu_global_state(void) {
180190
#else
181191
const char *lib_name = "libcuda.so";
182192
#endif
183-
// check if CUDA shared library is already loaded
184-
// we pass 0 as a handle to search the global symbol table
193+
// The CUDA shared library should be already loaded by the user
194+
// of the CUDA provider. UMF just want to reuse it
195+
// and increase the reference count to the CUDA shared library.
196+
void *lib_handle =
197+
utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_NO_LOAD);
198+
if (!lib_handle) {
199+
LOG_ERR("Failed to open CUDA shared library");
200+
Init_cu_global_state_failed = true;
201+
return;
202+
}
185203

186204
// NOTE: some symbols defined in the lib have _vX postfixes - it is
187205
// important to load the proper version of functions
188-
*(void **)&g_cu_ops.cuMemGetAllocationGranularity =
189-
utils_get_symbol_addr(0, "cuMemGetAllocationGranularity", lib_name);
206+
*(void **)&g_cu_ops.cuMemGetAllocationGranularity = utils_get_symbol_addr(
207+
lib_handle, "cuMemGetAllocationGranularity", lib_name);
190208
*(void **)&g_cu_ops.cuMemAlloc =
191-
utils_get_symbol_addr(0, "cuMemAlloc_v2", lib_name);
209+
utils_get_symbol_addr(lib_handle, "cuMemAlloc_v2", lib_name);
192210
*(void **)&g_cu_ops.cuMemHostAlloc =
193-
utils_get_symbol_addr(0, "cuMemHostAlloc", lib_name);
211+
utils_get_symbol_addr(lib_handle, "cuMemHostAlloc", lib_name);
194212
*(void **)&g_cu_ops.cuMemAllocManaged =
195-
utils_get_symbol_addr(0, "cuMemAllocManaged", lib_name);
213+
utils_get_symbol_addr(lib_handle, "cuMemAllocManaged", lib_name);
196214
*(void **)&g_cu_ops.cuMemFree =
197-
utils_get_symbol_addr(0, "cuMemFree_v2", lib_name);
215+
utils_get_symbol_addr(lib_handle, "cuMemFree_v2", lib_name);
198216
*(void **)&g_cu_ops.cuMemFreeHost =
199-
utils_get_symbol_addr(0, "cuMemFreeHost", lib_name);
217+
utils_get_symbol_addr(lib_handle, "cuMemFreeHost", lib_name);
200218
*(void **)&g_cu_ops.cuGetErrorName =
201-
utils_get_symbol_addr(0, "cuGetErrorName", lib_name);
219+
utils_get_symbol_addr(lib_handle, "cuGetErrorName", lib_name);
202220
*(void **)&g_cu_ops.cuGetErrorString =
203-
utils_get_symbol_addr(0, "cuGetErrorString", lib_name);
221+
utils_get_symbol_addr(lib_handle, "cuGetErrorString", lib_name);
204222
*(void **)&g_cu_ops.cuCtxGetCurrent =
205-
utils_get_symbol_addr(0, "cuCtxGetCurrent", lib_name);
223+
utils_get_symbol_addr(lib_handle, "cuCtxGetCurrent", lib_name);
206224
*(void **)&g_cu_ops.cuCtxSetCurrent =
207-
utils_get_symbol_addr(0, "cuCtxSetCurrent", lib_name);
225+
utils_get_symbol_addr(lib_handle, "cuCtxSetCurrent", lib_name);
208226
*(void **)&g_cu_ops.cuIpcGetMemHandle =
209-
utils_get_symbol_addr(0, "cuIpcGetMemHandle", lib_name);
227+
utils_get_symbol_addr(lib_handle, "cuIpcGetMemHandle", lib_name);
210228
*(void **)&g_cu_ops.cuIpcOpenMemHandle =
211-
utils_get_symbol_addr(0, "cuIpcOpenMemHandle_v2", lib_name);
229+
utils_get_symbol_addr(lib_handle, "cuIpcOpenMemHandle_v2", lib_name);
212230
*(void **)&g_cu_ops.cuIpcCloseMemHandle =
213-
utils_get_symbol_addr(0, "cuIpcCloseMemHandle", lib_name);
231+
utils_get_symbol_addr(lib_handle, "cuIpcCloseMemHandle", lib_name);
214232

215233
if (!g_cu_ops.cuMemGetAllocationGranularity || !g_cu_ops.cuMemAlloc ||
216234
!g_cu_ops.cuMemHostAlloc || !g_cu_ops.cuMemAllocManaged ||
@@ -221,7 +239,10 @@ static void init_cu_global_state(void) {
221239
!g_cu_ops.cuIpcCloseMemHandle) {
222240
LOG_FATAL("Required CUDA symbols not found.");
223241
Init_cu_global_state_failed = true;
242+
utils_close_library(lib_handle);
243+
return;
224244
}
245+
cu_lib_handle = lib_handle;
225246
}
226247

227248
umf_result_t umfCUDAMemoryProviderParamsCreate(
@@ -327,7 +348,7 @@ static umf_result_t cu_memory_provider_initialize(void *params,
327348
utils_init_once(&cu_is_initialized, init_cu_global_state);
328349
if (Init_cu_global_state_failed) {
329350
LOG_FATAL("Loading CUDA symbols failed");
330-
return UMF_RESULT_ERROR_UNKNOWN;
351+
return UMF_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
331352
}
332353

333354
cu_memory_provider_t *cu_provider =

src/provider/provider_cuda_internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
*
3+
* Copyright (C) 2025 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
void fini_cu_global_state(void);

src/provider/provider_level_zero.c

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@
1414
#include <umf/memory_provider_ops.h>
1515
#include <umf/providers/provider_level_zero.h>
1616

17+
#include "provider_level_zero_internal.h"
18+
#include "utils_load_library.h"
1719
#include "utils_log.h"
1820

21+
static void *ze_lib_handle = NULL;
22+
23+
void fini_ze_global_state(void) {
24+
if (ze_lib_handle) {
25+
utils_close_library(ze_lib_handle);
26+
ze_lib_handle = NULL;
27+
}
28+
}
29+
1930
#if defined(UMF_NO_LEVEL_ZERO_PROVIDER)
2031

2132
umf_result_t umfLevelZeroMemoryProviderParamsCreate(
@@ -105,7 +116,6 @@ umf_memory_provider_ops_t *umfLevelZeroMemoryProviderOps(void) {
105116
#include "utils_assert.h"
106117
#include "utils_common.h"
107118
#include "utils_concurrency.h"
108-
#include "utils_load_library.h"
109119
#include "utils_log.h"
110120
#include "utils_sanitizers.h"
111121
#include "ze_api.h"
@@ -207,32 +217,41 @@ static void init_ze_global_state(void) {
207217
#else
208218
const char *lib_name = "libze_loader.so";
209219
#endif
210-
// check if Level Zero shared library is already loaded
211-
// we pass 0 as a handle to search the global symbol table
220+
// The Level Zero shared library should be already loaded by the user
221+
// of the Level Zero provider. UMF just want to reuse it
222+
// and increase the reference count to the Level Zero shared library.
223+
void *lib_handle =
224+
utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_NO_LOAD);
225+
if (!lib_handle) {
226+
LOG_FATAL("Failed to open Level Zero shared library");
227+
Init_ze_global_state_failed = true;
228+
return;
229+
}
230+
212231
*(void **)&g_ze_ops.zeMemAllocHost =
213-
utils_get_symbol_addr(0, "zeMemAllocHost", lib_name);
232+
utils_get_symbol_addr(lib_handle, "zeMemAllocHost", lib_name);
214233
*(void **)&g_ze_ops.zeMemAllocDevice =
215-
utils_get_symbol_addr(0, "zeMemAllocDevice", lib_name);
234+
utils_get_symbol_addr(lib_handle, "zeMemAllocDevice", lib_name);
216235
*(void **)&g_ze_ops.zeMemAllocShared =
217-
utils_get_symbol_addr(0, "zeMemAllocShared", lib_name);
236+
utils_get_symbol_addr(lib_handle, "zeMemAllocShared", lib_name);
218237
*(void **)&g_ze_ops.zeMemFree =
219-
utils_get_symbol_addr(0, "zeMemFree", lib_name);
238+
utils_get_symbol_addr(lib_handle, "zeMemFree", lib_name);
220239
*(void **)&g_ze_ops.zeMemGetIpcHandle =
221-
utils_get_symbol_addr(0, "zeMemGetIpcHandle", lib_name);
240+
utils_get_symbol_addr(lib_handle, "zeMemGetIpcHandle", lib_name);
222241
*(void **)&g_ze_ops.zeMemPutIpcHandle =
223-
utils_get_symbol_addr(0, "zeMemPutIpcHandle", lib_name);
242+
utils_get_symbol_addr(lib_handle, "zeMemPutIpcHandle", lib_name);
224243
*(void **)&g_ze_ops.zeMemOpenIpcHandle =
225-
utils_get_symbol_addr(0, "zeMemOpenIpcHandle", lib_name);
244+
utils_get_symbol_addr(lib_handle, "zeMemOpenIpcHandle", lib_name);
226245
*(void **)&g_ze_ops.zeMemCloseIpcHandle =
227-
utils_get_symbol_addr(0, "zeMemCloseIpcHandle", lib_name);
228-
*(void **)&g_ze_ops.zeContextMakeMemoryResident =
229-
utils_get_symbol_addr(0, "zeContextMakeMemoryResident", lib_name);
246+
utils_get_symbol_addr(lib_handle, "zeMemCloseIpcHandle", lib_name);
247+
*(void **)&g_ze_ops.zeContextMakeMemoryResident = utils_get_symbol_addr(
248+
lib_handle, "zeContextMakeMemoryResident", lib_name);
230249
*(void **)&g_ze_ops.zeDeviceGetProperties =
231-
utils_get_symbol_addr(0, "zeDeviceGetProperties", lib_name);
250+
utils_get_symbol_addr(lib_handle, "zeDeviceGetProperties", lib_name);
232251
*(void **)&g_ze_ops.zeMemFreeExt =
233-
utils_get_symbol_addr(0, "zeMemFreeExt", lib_name);
252+
utils_get_symbol_addr(lib_handle, "zeMemFreeExt", lib_name);
234253
*(void **)&g_ze_ops.zeMemGetAllocProperties =
235-
utils_get_symbol_addr(0, "zeMemGetAllocProperties", lib_name);
254+
utils_get_symbol_addr(lib_handle, "zeMemGetAllocProperties", lib_name);
236255

237256
if (!g_ze_ops.zeMemAllocHost || !g_ze_ops.zeMemAllocDevice ||
238257
!g_ze_ops.zeMemAllocShared || !g_ze_ops.zeMemFree ||
@@ -244,7 +263,10 @@ static void init_ze_global_state(void) {
244263
// starting from Level Zero 1.6
245264
LOG_FATAL("Required Level Zero symbols not found.");
246265
Init_ze_global_state_failed = true;
266+
utils_close_library(lib_handle);
267+
return;
247268
}
269+
ze_lib_handle = lib_handle;
248270
}
249271

250272
umf_result_t umfLevelZeroMemoryProviderParamsCreate(
@@ -551,7 +573,7 @@ static umf_result_t ze_memory_provider_initialize(void *params,
551573
utils_init_once(&ze_is_initialized, init_ze_global_state);
552574
if (Init_ze_global_state_failed) {
553575
LOG_FATAL("Loading Level Zero symbols failed");
554-
return UMF_RESULT_ERROR_UNKNOWN;
576+
return UMF_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
555577
}
556578

557579
ze_memory_provider_t *ze_provider =
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
*
3+
* Copyright (C) 2025 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
void fini_ze_global_state(void);

src/utils/utils_level_zero.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,15 @@ int InitLevelZeroOps() {
144144
const char *lib_name = "libze_loader.so";
145145
#endif
146146
// Load Level Zero symbols
147-
// NOTE that we use UMF_UTIL_OPEN_LIBRARY_GLOBAL which add all loaded symbols to the
147+
#if OPEN_ZE_LIBRARY_GLOBAL
148+
// NOTE UMF_UTIL_OPEN_LIBRARY_GLOBAL adds all loaded symbols to the
148149
// global symbol table.
150+
int open_flags = UMF_UTIL_OPEN_LIBRARY_GLOBAL;
151+
#else
152+
int open_flags = 0;
153+
#endif
149154
zeDlHandle = std::unique_ptr<void, DlHandleCloser>(
150-
utils_open_library(lib_name, UMF_UTIL_OPEN_LIBRARY_GLOBAL));
155+
utils_open_library(lib_name, open_flags));
151156
*(void **)&libze_ops.zeInit =
152157
utils_get_symbol_addr(zeDlHandle.get(), "zeInit", lib_name);
153158
if (libze_ops.zeInit == nullptr) {

0 commit comments

Comments
 (0)