Skip to content

Commit 91a37cf

Browse files
committed
Delete Adapter in atexit after refcnt is 0 due to multi DLLMain
- In Windows, SYCL and UMF both define DLLMain such that a DLLMain for only the adapter's is not possible. To fix this, the L0 adapter inits the global adapter at variable init and registers an atexit teardown after refcnt == 0. Signed-off-by: Neil R. Spruit <neil.r.spruit@intel.com>
1 parent aa69079 commit 91a37cf

File tree

8 files changed

+52
-63
lines changed

8 files changed

+52
-63
lines changed

source/adapters/level_zero/CMakeLists.txt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022 Intel Corporation
1+
# Copyright (C) 2022-2024 Intel Corporation
22
# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
33
# See LICENSE.TXT
44
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -122,12 +122,7 @@ add_ur_adapter(${TARGET_NAME}
122122
${CMAKE_CURRENT_SOURCE_DIR}/../../ur/ur.cpp
123123
)
124124

125-
if(WIN32)
126-
target_sources(ur_adapter_level_zero
127-
PRIVATE
128-
${CMAKE_CURRENT_SOURCE_DIR}/adapter_lib_init_windows.cpp
129-
)
130-
else()
125+
if(NOT WIN32)
131126
target_sources(ur_adapter_level_zero
132127
PRIVATE
133128
${CMAKE_CURRENT_SOURCE_DIR}/adapter_lib_init_linux.cpp

source/adapters/level_zero/adapter.cpp

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
#include "adapter.hpp"
1212
#include "ur_level_zero.hpp"
1313

14-
ur_adapter_handle_t_ *Adapter;
14+
// Due to multiple DLLMain definitions with SYCL, Global Adapter is init at
15+
// variable creation.
16+
#if defined(_WIN32)
17+
ur_adapter_handle_t_ *GlobalAdapter = new ur_adapter_handle_t_();
18+
#else
19+
ur_adapter_handle_t_ *GlobalAdapter;
20+
#endif
1521

1622
ur_result_t initPlatforms(PlatformVec &platforms) noexcept try {
1723
uint32_t ZeDriverCount = 0;
@@ -53,7 +59,7 @@ ur_adapter_handle_t_::ur_adapter_handle_t_() {
5359
}
5460

5561
// initialize level zero only once.
56-
if (Adapter->ZeResult == std::nullopt) {
62+
if (GlobalAdapter->ZeResult == std::nullopt) {
5763
// Setting these environment variables before running zeInit will enable
5864
// the validation layer in the Level Zero loader.
5965
if (UrL0Debug & UR_L0_DEBUG_VALIDATION) {
@@ -72,20 +78,21 @@ ur_adapter_handle_t_::ur_adapter_handle_t_() {
7278
// We must only initialize the driver once, even if urPlatformGet() is
7379
// called multiple times. Declaring the return value as "static" ensures
7480
// it's only called once.
75-
Adapter->ZeResult = ZE_CALL_NOCHECK(zeInit, (ZE_INIT_FLAG_GPU_ONLY));
81+
GlobalAdapter->ZeResult =
82+
ZE_CALL_NOCHECK(zeInit, (ZE_INIT_FLAG_GPU_ONLY));
7683
}
77-
assert(Adapter->ZeResult !=
84+
assert(GlobalAdapter->ZeResult !=
7885
std::nullopt); // verify that level-zero is initialized
7986
PlatformVec platforms;
8087

8188
// Absorb the ZE_RESULT_ERROR_UNINITIALIZED and just return 0 Platforms.
82-
if (*Adapter->ZeResult == ZE_RESULT_ERROR_UNINITIALIZED) {
89+
if (*GlobalAdapter->ZeResult == ZE_RESULT_ERROR_UNINITIALIZED) {
8390
result = std::move(platforms);
8491
return;
8592
}
86-
if (*Adapter->ZeResult != ZE_RESULT_SUCCESS) {
93+
if (*GlobalAdapter->ZeResult != ZE_RESULT_SUCCESS) {
8794
urPrint("zeInit: Level Zero initialization failure\n");
88-
result = ze2urResult(*Adapter->ZeResult);
95+
result = ze2urResult(*GlobalAdapter->ZeResult);
8996
return;
9097
}
9198

@@ -98,6 +105,14 @@ ur_adapter_handle_t_::ur_adapter_handle_t_() {
98105
};
99106
}
100107

108+
#if defined(_WIN32)
109+
void globalAdapterWindowsCleanup() {
110+
if (GlobalAdapter) {
111+
delete GlobalAdapter;
112+
}
113+
}
114+
#endif
115+
101116
ur_result_t adapterStateTeardown() {
102117
bool LeakFound = false;
103118

@@ -183,6 +198,11 @@ ur_result_t adapterStateTeardown() {
183198
}
184199
if (LeakFound)
185200
return UR_RESULT_ERROR_INVALID_MEM_OBJECT;
201+
// Due to multiple DLLMain definitions with SYCL, register to cleanup the
202+
// Global Adapter after refcnt is 0
203+
#if defined(_WIN32)
204+
std::atexit(globalAdapterWindowsCleanup);
205+
#endif
186206

187207
return UR_RESULT_SUCCESS;
188208
}
@@ -202,12 +222,12 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterGet(
202222
///< adapters available.
203223
) {
204224
if (NumEntries > 0 && Adapters) {
205-
if (Adapter) {
206-
std::lock_guard<std::mutex> Lock{Adapter->Mutex};
207-
if (Adapter->RefCount++ == 0) {
225+
if (GlobalAdapter) {
226+
std::lock_guard<std::mutex> Lock{GlobalAdapter->Mutex};
227+
if (GlobalAdapter->RefCount++ == 0) {
208228
adapterStateInit();
209229
}
210-
*Adapters = Adapter;
230+
*Adapters = GlobalAdapter;
211231
} else {
212232
return UR_RESULT_ERROR_UNINITIALIZED;
213233
}
@@ -222,9 +242,9 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterGet(
222242

223243
UR_APIEXPORT ur_result_t UR_APICALL urAdapterRelease(ur_adapter_handle_t) {
224244
// Check first if the Adapter pointer is valid
225-
if (Adapter) {
226-
std::lock_guard<std::mutex> Lock{Adapter->Mutex};
227-
if (--Adapter->RefCount == 0) {
245+
if (GlobalAdapter) {
246+
std::lock_guard<std::mutex> Lock{GlobalAdapter->Mutex};
247+
if (--GlobalAdapter->RefCount == 0) {
228248
return adapterStateTeardown();
229249
}
230250
}
@@ -233,9 +253,9 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterRelease(ur_adapter_handle_t) {
233253
}
234254

235255
UR_APIEXPORT ur_result_t UR_APICALL urAdapterRetain(ur_adapter_handle_t) {
236-
if (Adapter) {
237-
std::lock_guard<std::mutex> Lock{Adapter->Mutex};
238-
Adapter->RefCount++;
256+
if (GlobalAdapter) {
257+
std::lock_guard<std::mutex> Lock{GlobalAdapter->Mutex};
258+
GlobalAdapter->RefCount++;
239259
} else {
240260
return UR_RESULT_ERROR_UNINITIALIZED;
241261
}
@@ -267,7 +287,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterGetInfo(ur_adapter_handle_t,
267287
case UR_ADAPTER_INFO_BACKEND:
268288
return ReturnValue(UR_ADAPTER_BACKEND_LEVEL_ZERO);
269289
case UR_ADAPTER_INFO_REFERENCE_COUNT:
270-
return ReturnValue(Adapter->RefCount.load());
290+
return ReturnValue(GlobalAdapter->RefCount.load());
271291
default:
272292
return UR_RESULT_ERROR_INVALID_ENUMERATION;
273293
}

source/adapters/level_zero/adapter.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ struct ur_adapter_handle_t_ {
2525
ZeCache<Result<PlatformVec>> PlatformCache;
2626
};
2727

28-
extern ur_adapter_handle_t_ *Adapter;
28+
extern ur_adapter_handle_t_ *GlobalAdapter;

source/adapters/level_zero/adapter_lib_init_linux.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
#include "ur_level_zero.hpp"
1313

1414
void __attribute__((constructor)) createAdapterHandle() {
15-
if (!Adapter) {
16-
Adapter = new ur_adapter_handle_t_();
15+
if (!GlobalAdapter) {
16+
GlobalAdapter = new ur_adapter_handle_t_();
1717
}
1818
}
1919

2020
void __attribute__((destructor)) deleteAdapterHandle() {
21-
if (Adapter) {
22-
delete Adapter;
21+
if (GlobalAdapter) {
22+
delete GlobalAdapter;
23+
GlobalAdapter = nullptr;
2324
}
2425
}

source/adapters/level_zero/adapter_lib_init_windows.cpp

Lines changed: 0 additions & 27 deletions
This file was deleted.

source/adapters/level_zero/device.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceCreateWithNativeHandle(
14421442
// a valid Level Zero device.
14431443

14441444
ur_device_handle_t Dev = nullptr;
1445-
if (const auto *platforms = Adapter->PlatformCache->get_value()) {
1445+
if (const auto *platforms = GlobalAdapter->PlatformCache->get_value()) {
14461446
for (const auto &p : *platforms) {
14471447
Dev = p->getDeviceFromNativeHandle(ZeDevice);
14481448
if (Dev) {
@@ -1453,7 +1453,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceCreateWithNativeHandle(
14531453
}
14541454
}
14551455
} else {
1456-
return Adapter->PlatformCache->get_error();
1456+
return GlobalAdapter->PlatformCache->get_error();
14571457
}
14581458

14591459
if (Dev == nullptr)

source/adapters/level_zero/platform.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urPlatformGet(
2929
) {
3030
// Platform handles are cached for reuse. This is to ensure consistent
3131
// handle pointers across invocations and to improve retrieval performance.
32-
if (const auto *cached_platforms = Adapter->PlatformCache->get_value();
32+
if (const auto *cached_platforms = GlobalAdapter->PlatformCache->get_value();
3333
cached_platforms) {
3434
uint32_t nplatforms = (uint32_t)cached_platforms->size();
3535
if (NumPlatforms) {
@@ -41,7 +41,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urPlatformGet(
4141
}
4242
}
4343
} else {
44-
return Adapter->PlatformCache->get_error();
44+
return GlobalAdapter->PlatformCache->get_error();
4545
}
4646

4747
return UR_RESULT_SUCCESS;
@@ -133,7 +133,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urPlatformCreateWithNativeHandle(
133133
auto ZeDriver = ur_cast<ze_driver_handle_t>(NativePlatform);
134134

135135
uint32_t NumPlatforms = 0;
136-
ur_adapter_handle_t AdapterHandle = Adapter;
136+
ur_adapter_handle_t AdapterHandle = GlobalAdapter;
137137
UR_CALL(urPlatformGet(&AdapterHandle, 1, 0, nullptr, &NumPlatforms));
138138

139139
if (NumPlatforms) {

source/adapters/level_zero/queue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urQueueCreateWithNativeHandle(
569569
// Maybe this is not completely correct.
570570
uint32_t NumEntries = 1;
571571
ur_platform_handle_t Platform{};
572-
ur_adapter_handle_t AdapterHandle = Adapter;
572+
ur_adapter_handle_t AdapterHandle = GlobalAdapter;
573573
UR_CALL(urPlatformGet(&AdapterHandle, 1, NumEntries, &Platform, nullptr));
574574

575575
ur_device_handle_t UrDevice = Device;

0 commit comments

Comments
 (0)