diff --git a/unified-runtime/cmake/FetchLevelZero.cmake b/unified-runtime/cmake/FetchLevelZero.cmake index c4d0c954278d2..db0ff95e1ed29 100644 --- a/unified-runtime/cmake/FetchLevelZero.cmake +++ b/unified-runtime/cmake/FetchLevelZero.cmake @@ -43,7 +43,7 @@ if (NOT DEFINED LEVEL_ZERO_LIBRARY OR NOT DEFINED LEVEL_ZERO_INCLUDE_DIR) set(UR_LEVEL_ZERO_LOADER_REPO "https://github.com/oneapi-src/level-zero.git") endif() if (UR_LEVEL_ZERO_LOADER_TAG STREQUAL "") - set(UR_LEVEL_ZERO_LOADER_TAG v1.21.1) + set(UR_LEVEL_ZERO_LOADER_TAG ecfe375b30cc04265b20ac1b7996a85d0910f3ed) endif() # Disable due to a bug https://github.com/oneapi-src/level-zero/issues/104 diff --git a/unified-runtime/source/adapters/level_zero/command_buffer.cpp b/unified-runtime/source/adapters/level_zero/command_buffer.cpp index 45ab74c52a969..8ebc0d1661611 100644 --- a/unified-runtime/source/adapters/level_zero/command_buffer.cpp +++ b/unified-runtime/source/adapters/level_zero/command_buffer.cpp @@ -445,16 +445,16 @@ void ur_exp_command_buffer_handle_t_::cleanupCommandBufferResources() { // Release the memory allocated to the CommandList stored in the // command_buffer - if (ZeComputeCommandList) { + if (ZeComputeCommandList && checkL0LoaderTeardown()) { ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeComputeCommandList)); } - if (useCopyEngine() && ZeCopyCommandList) { + if (useCopyEngine() && ZeCopyCommandList && checkL0LoaderTeardown()) { ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeCopyCommandList)); } // Release the memory allocated to the CommandListResetEvents stored in the // command_buffer - if (ZeCommandListResetEvents) { + if (ZeCommandListResetEvents && checkL0LoaderTeardown()) { ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeCommandListResetEvents)); } @@ -502,7 +502,9 @@ void ur_exp_command_buffer_handle_t_::cleanupCommandBufferResources() { // Release fences allocated to command-buffer for (auto &ZeFencePair : ZeFencesMap) { auto &ZeFence = ZeFencePair.second; - ZE_CALL_NOCHECK(zeFenceDestroy, (ZeFence)); + if (checkL0LoaderTeardown()) { + ZE_CALL_NOCHECK(zeFenceDestroy, (ZeFence)); + } } auto ReleaseIndirectMem = [](ur_kernel_handle_t Kernel) { diff --git a/unified-runtime/source/adapters/level_zero/common.hpp b/unified-runtime/source/adapters/level_zero/common.hpp index 11b87d9ed276b..592631901fd24 100644 --- a/unified-runtime/source/adapters/level_zero/common.hpp +++ b/unified-runtime/source/adapters/level_zero/common.hpp @@ -25,6 +25,7 @@ #include #endif +#include #include #include #include @@ -38,65 +39,15 @@ struct _ur_platform_handle_t; [[maybe_unused]] static bool checkL0LoaderTeardown() { - bool loaderStable = true; -#ifdef _WIN32 - uint32_t ZeDriverCount = 0; - HMODULE zeLoader = LoadLibrary("ze_loader.dll"); - if (zeLoader) { - typedef ze_result_t (*zeDriverGet_t)(uint32_t *, ze_driver_handle_t *); - zeDriverGet_t zeDriverGetLoader = - (zeDriverGet_t)GetProcAddress(zeLoader, "zeDriverGet"); - if (zeDriverGetLoader) { - ze_result_t result = zeDriverGetLoader(&ZeDriverCount, nullptr); - logger::debug( - "ZE ---> checkL0LoaderTeardown result = {} driver count = {}", result, - ZeDriverCount); - if (result != ZE_RESULT_SUCCESS || ZeDriverCount == 0) { - loaderStable = false; - } - } else { - logger::debug("ZE ---> checkL0LoaderTeardown: Failed to get address of " - "zeDriverGet"); - loaderStable = false; - } - FreeLibrary(zeLoader); - } else { - logger::debug( - "ZE ---> checkL0LoaderTeardown: Failed to load ze_loader.dll"); - loaderStable = false; - } -#else - uint32_t ZeDriverCount = 0; - void *zeLoader = dlopen("libze_loader.so.1", RTLD_LAZY); - if (zeLoader) { - typedef ze_result_t (*zeDriverGet_t)(uint32_t *, ze_driver_handle_t *); - zeDriverGet_t zeDriverGetLoader = - (zeDriverGet_t)dlsym(zeLoader, "zeDriverGet"); - if (zeDriverGetLoader) { - ze_result_t result = zeDriverGetLoader(&ZeDriverCount, nullptr); - logger::debug( - "ZE ---> checkL0LoaderTeardown result = {} driver count = {}", result, - ZeDriverCount); - if (result != ZE_RESULT_SUCCESS || ZeDriverCount == 0) { - loaderStable = false; - } - } else { - logger::debug("ZE ---> checkL0LoaderTeardown: Failed to get address of " - "zeDriverGet"); - loaderStable = false; + try { + if (!zelCheckIsLoaderInTearDown()) { + return true; } - dlclose(zeLoader); - } else { - logger::debug( - "ZE ---> checkL0LoaderTeardown: Failed to load libze_loader.so.1"); - loaderStable = false; + } catch (...) { } -#endif - if (!loaderStable) { - logger::debug( - "ZE ---> checkL0LoaderTeardown: Loader is not stable, returning false"); - } - return loaderStable; + logger::debug( + "ZE ---> checkL0LoaderTeardown: Loader is in teardown or is unstable"); + return false; } // Controls UR L0 calls tracing. @@ -329,9 +280,6 @@ struct _ur_object { // Indicates if we own the native handle or it came from interop that // asked to not transfer the ownership to SYCL RT. bool OwnNativeHandle = false; - - // Indicates if this object is an interop handle. - bool IsInteropNativeHandle = false; }; // Record for a memory allocation. This structure is used to keep information diff --git a/unified-runtime/source/adapters/level_zero/context.cpp b/unified-runtime/source/adapters/level_zero/context.cpp index de1ca00f9f8fe..6cbd9a0709cdc 100644 --- a/unified-runtime/source/adapters/level_zero/context.cpp +++ b/unified-runtime/source/adapters/level_zero/context.cpp @@ -152,7 +152,6 @@ ur_result_t urContextCreateWithNativeHandle( ur_context_handle_t_ *UrContext = new ur_context_handle_t_( ZeContext, NumDevices, Devices, OwnNativeHandle); UrContext->initialize(); - UrContext->IsInteropNativeHandle = true; *Context = reinterpret_cast(UrContext); } catch (const std::bad_alloc &) { return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; @@ -264,11 +263,8 @@ ur_result_t ContextReleaseHelper(ur_context_handle_t Context) { Contexts.erase(It); } ze_context_handle_t DestroyZeContext = - ((Context->OwnNativeHandle && !Context->IsInteropNativeHandle) || - (Context->OwnNativeHandle && Context->IsInteropNativeHandle && - checkL0LoaderTeardown())) - ? Context->ZeContext - : nullptr; + (Context->OwnNativeHandle && checkL0LoaderTeardown()) ? Context->ZeContext + : nullptr; // Clean up any live memory associated with Context ur_result_t Result = Context->finalize(); @@ -285,8 +281,12 @@ ur_result_t ContextReleaseHelper(ur_context_handle_t Context) { if (DestroyZeContext) { auto ZeResult = ZE_CALL_NOCHECK(zeContextDestroy, (DestroyZeContext)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } return Result; @@ -307,12 +307,15 @@ ur_result_t ur_context_handle_t_::finalize() { std::scoped_lock Lock(EventCacheMutex); for (auto &EventCache : EventCaches) { for (auto &Event : EventCache) { - if (!Event->IsInteropNativeHandle || - (Event->IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeEventDestroy, (Event->ZeEvent)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } Event->ZeEvent = nullptr; delete Event; @@ -324,41 +327,61 @@ ur_result_t ur_context_handle_t_::finalize() { std::scoped_lock Lock(ZeEventPoolCacheMutex); for (auto &ZePoolCache : ZeEventPoolCache) { for (auto &ZePool : ZePoolCache) { - auto ZeResult = ZE_CALL_NOCHECK(zeEventPoolDestroy, (ZePool)); - // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) - return ze2urResult(ZeResult); + if (checkL0LoaderTeardown()) { + auto ZeResult = ZE_CALL_NOCHECK(zeEventPoolDestroy, (ZePool)); + // Gracefully handle the case that L0 was already unloaded. + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) + return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } + } } ZePoolCache.clear(); } } - // Destroy the command list used for initializations - auto ZeResult = ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeCommandListInit)); - // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) - return ze2urResult(ZeResult); + if (checkL0LoaderTeardown()) { + // Destroy the command list used for initializations + auto ZeResult = ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeCommandListInit)); + // Gracefully handle the case that L0 was already unloaded. + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) + return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } + } std::scoped_lock Lock(ZeCommandListCacheMutex); for (auto &List : ZeComputeCommandListCache) { for (auto &Item : List.second) { ze_command_list_handle_t ZeCommandList = Item.first; - if (ZeCommandList) { + if (ZeCommandList && checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeCommandList)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } } } for (auto &List : ZeCopyCommandListCache) { for (auto &Item : List.second) { ze_command_list_handle_t ZeCommandList = Item.first; - if (ZeCommandList) { + if (ZeCommandList && checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeCommandListDestroy, (ZeCommandList)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } } } diff --git a/unified-runtime/source/adapters/level_zero/device.cpp b/unified-runtime/source/adapters/level_zero/device.cpp index 00a5cc4b2d82a..73d8e6e32eda7 100644 --- a/unified-runtime/source/adapters/level_zero/device.cpp +++ b/unified-runtime/source/adapters/level_zero/device.cpp @@ -1536,7 +1536,6 @@ ur_result_t urDeviceCreateWithNativeHandle( if (Dev == nullptr) return UR_RESULT_ERROR_INVALID_VALUE; - Dev->IsInteropNativeHandle = true; *Device = Dev; return UR_RESULT_SUCCESS; } diff --git a/unified-runtime/source/adapters/level_zero/event.cpp b/unified-runtime/source/adapters/level_zero/event.cpp index 11c0502a55939..977d0b28a9b3f 100644 --- a/unified-runtime/source/adapters/level_zero/event.cpp +++ b/unified-runtime/source/adapters/level_zero/event.cpp @@ -1001,7 +1001,6 @@ ur_result_t urEventCreateWithNativeHandle( UREvent->CleanedUp = true; *Event = reinterpret_cast(UREvent); - UREvent->IsInteropNativeHandle = true; return UR_RESULT_SUCCESS; } @@ -1090,7 +1089,7 @@ ur_result_t ur_event_handle_t_::getOrCreateHostVisibleEvent( * leaks or resource mismanagement. */ ur_event_handle_t_::~ur_event_handle_t_() { - if (this->ZeEvent && this->Completed) { + if (this->ZeEvent && this->Completed && checkL0LoaderTeardown()) { if (this->UrQueue && !this->UrQueue->isDiscardEvents()) ZE_CALL_NOCHECK(zeEventDestroy, (this->ZeEvent)); } @@ -1121,12 +1120,15 @@ ur_result_t urEventReleaseInternal(ur_event_handle_t Event) { } if (Event->OwnNativeHandle) { if (DisableEventsCaching) { - if (!Event->IsInteropNativeHandle || - (Event->IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeEventDestroy, (Event->ZeEvent)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } Event->ZeEvent = nullptr; auto Context = Event->Context; diff --git a/unified-runtime/source/adapters/level_zero/image.cpp b/unified-runtime/source/adapters/level_zero/image.cpp index 24b2a8cfca758..c493069ed4205 100644 --- a/unified-runtime/source/adapters/level_zero/image.cpp +++ b/unified-runtime/source/adapters/level_zero/image.cpp @@ -313,7 +313,9 @@ ur_result_t urBindlessImagesUnsampledImageHandleDestroyExp( auto item = hDevice->ZeOffsetToImageHandleMap.find(hImage); if (item != hDevice->ZeOffsetToImageHandleMap.end()) { - ZE2UR_CALL(zeImageDestroy, (item->second)); + if (checkL0LoaderTeardown()) { + ZE2UR_CALL(zeImageDestroy, (item->second)); + } hDevice->ZeOffsetToImageHandleMap.erase(item); } else { return UR_RESULT_ERROR_INVALID_NULL_HANDLE; diff --git a/unified-runtime/source/adapters/level_zero/kernel.cpp b/unified-runtime/source/adapters/level_zero/kernel.cpp index d9dd4cc38ad0a..3a54f4576f822 100644 --- a/unified-runtime/source/adapters/level_zero/kernel.cpp +++ b/unified-runtime/source/adapters/level_zero/kernel.cpp @@ -940,12 +940,15 @@ ur_result_t urKernelRelease( auto KernelProgram = Kernel->Program; if (Kernel->OwnNativeHandle) { for (auto &ZeKernel : Kernel->ZeKernels) { - if (!Kernel->IsInteropNativeHandle || - (Kernel->IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeKernelDestroy, (ZeKernel)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } } } @@ -1157,7 +1160,6 @@ ur_result_t urKernelCreateWithNativeHandle( } Kernel->Program = Program; - Kernel->IsInteropNativeHandle = true; UR_CALL(Kernel->initialize()); diff --git a/unified-runtime/source/adapters/level_zero/memory.cpp b/unified-runtime/source/adapters/level_zero/memory.cpp index 1a348c8ef9b6e..cb9e90ceb1509 100644 --- a/unified-runtime/source/adapters/level_zero/memory.cpp +++ b/unified-runtime/source/adapters/level_zero/memory.cpp @@ -1563,7 +1563,6 @@ ur_result_t urMemImageCreateWithNativeHandle( auto OwnNativeHandle = Properties ? Properties->isNativeHandleOwned : false; UR_CALL(createUrMemFromZeImage(Context, ZeHImage, OwnNativeHandle, ZeImageDesc, Mem)); - (*Mem)->IsInteropNativeHandle = true; return UR_RESULT_SUCCESS; } @@ -1663,13 +1662,16 @@ ur_result_t urMemRelease( if (Image->OwnNativeHandle) { UR_CALL(Mem->getZeHandle(ZeHandleImage, ur_mem_handle_t_::write_only, nullptr, nullptr, 0u)); - if (!Image->IsInteropNativeHandle || - (Image->IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK( zeImageDestroy, (ur_cast(ZeHandleImage))); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } } delete Image; @@ -1776,7 +1778,6 @@ ur_result_t urMemBufferCreateWithNativeHandle( Buffer = new _ur_buffer(Context, Size, Device, ur_cast(NativeMem), OwnNativeHandle); *Mem = reinterpret_cast(Buffer); - (*Mem)->IsInteropNativeHandle = true; } catch (const std::bad_alloc &) { return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; } catch (...) { diff --git a/unified-runtime/source/adapters/level_zero/physical_mem.cpp b/unified-runtime/source/adapters/level_zero/physical_mem.cpp index 836f574800c1e..5d4d0acce0eb3 100644 --- a/unified-runtime/source/adapters/level_zero/physical_mem.cpp +++ b/unified-runtime/source/adapters/level_zero/physical_mem.cpp @@ -50,8 +50,10 @@ ur_result_t urPhysicalMemRelease(ur_physical_mem_handle_t hPhysicalMem) { if (!hPhysicalMem->RefCount.decrementAndTest()) return UR_RESULT_SUCCESS; - ZE2UR_CALL(zePhysicalMemDestroy, (hPhysicalMem->Context->getZeHandle(), - hPhysicalMem->ZePhysicalMem)); + if (checkL0LoaderTeardown()) { + ZE2UR_CALL(zePhysicalMemDestroy, (hPhysicalMem->Context->getZeHandle(), + hPhysicalMem->ZePhysicalMem)); + } delete hPhysicalMem; return UR_RESULT_SUCCESS; diff --git a/unified-runtime/source/adapters/level_zero/program.cpp b/unified-runtime/source/adapters/level_zero/program.cpp index 199ecad21af9b..c2bae5d971d9a 100644 --- a/unified-runtime/source/adapters/level_zero/program.cpp +++ b/unified-runtime/source/adapters/level_zero/program.cpp @@ -966,7 +966,6 @@ ur_result_t urProgramCreateWithNativeHandle( ur_program_handle_t_::Exe, Context, ZeModule, Properties ? Properties->isNativeHandleOwned : false); *Program = reinterpret_cast(UrProgram); - (*Program)->IsInteropNativeHandle = true; } catch (const std::bad_alloc &) { return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; } catch (...) { @@ -1078,7 +1077,7 @@ void ur_program_handle_t_::ur_release_program_resources(bool deletion) { } if (!resourcesReleased) { for (auto &[ZeDevice, DeviceData] : this->DeviceDataMap) { - if (DeviceData.ZeBuildLog) + if (DeviceData.ZeBuildLog && checkL0LoaderTeardown()) ZE_CALL_NOCHECK(zeModuleBuildLogDestroy, (DeviceData.ZeBuildLog)); } // interop api @@ -1087,7 +1086,7 @@ void ur_program_handle_t_::ur_release_program_resources(bool deletion) { } for (auto &[ZeDevice, DeviceData] : this->DeviceDataMap) - if (DeviceData.ZeModule) + if (DeviceData.ZeModule && checkL0LoaderTeardown()) ZE_CALL_NOCHECK(zeModuleDestroy, (DeviceData.ZeModule)); this->DeviceDataMap.clear(); diff --git a/unified-runtime/source/adapters/level_zero/queue.cpp b/unified-runtime/source/adapters/level_zero/queue.cpp index d4cea7faa9d6e..8ae288340918e 100644 --- a/unified-runtime/source/adapters/level_zero/queue.cpp +++ b/unified-runtime/source/adapters/level_zero/queue.cpp @@ -648,11 +648,16 @@ ur_result_t urQueueRelease( // runtime. Destroy only if a queue is healthy. Destroying a fence may // cause a hang otherwise. // If the fence is a nullptr we are using immediate commandlists. - if (Queue->Healthy && it->second.ZeFence != nullptr) { + if (Queue->Healthy && it->second.ZeFence != nullptr && + checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeFenceDestroy, (it->second.ZeFence)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } if (Queue->UsingImmCmdLists && Queue->OwnZeCommandQueue) { std::scoped_lock Lock( @@ -676,7 +681,7 @@ ur_result_t urQueueRelease( // A non-reusable comamnd list that came from a make_queue call is // destroyed since it cannot be recycled. ze_command_list_handle_t ZeCommandList = it->first; - if (ZeCommandList) { + if (ZeCommandList && checkL0LoaderTeardown()) { ZE2UR_CALL(zeCommandListDestroy, (ZeCommandList)); } } @@ -800,7 +805,6 @@ ur_result_t urQueueCreateWithNativeHandle( ur_queue_handle_t_ *Queue = new ur_queue_handle_t_( ComputeQueues, CopyQueues, Context, UrDevice, OwnNativeHandle, Flags); *RetQueue = reinterpret_cast(Queue); - (*RetQueue)->IsInteropNativeHandle = true; } catch (const std::bad_alloc &) { return UR_RESULT_ERROR_OUT_OF_RESOURCES; } catch (...) { @@ -1605,12 +1609,15 @@ ur_result_t urQueueReleaseInternal(ur_queue_handle_t Queue) { for (auto &QueueGroup : QueueMap) for (auto &ZeQueue : QueueGroup.second.ZeQueues) if (ZeQueue) { - if (!Queue->IsInteropNativeHandle || - (Queue->IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeCommandQueueDestroy, (ZeQueue)); // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } } } diff --git a/unified-runtime/source/adapters/level_zero/sampler.cpp b/unified-runtime/source/adapters/level_zero/sampler.cpp index f239dfed5ce49..59672ebc00bda 100644 --- a/unified-runtime/source/adapters/level_zero/sampler.cpp +++ b/unified-runtime/source/adapters/level_zero/sampler.cpp @@ -129,10 +129,16 @@ ur_result_t urSamplerRelease( if (!Sampler->RefCount.decrementAndTest()) return UR_RESULT_SUCCESS; - auto ZeResult = ZE_CALL_NOCHECK(zeSamplerDestroy, (Sampler->ZeSampler)); - // Gracefully handle the case that L0 was already unloaded. - if (ZeResult && ZeResult != ZE_RESULT_ERROR_UNINITIALIZED) - return ze2urResult(ZeResult); + if (checkL0LoaderTeardown()) { + auto ZeResult = ZE_CALL_NOCHECK(zeSamplerDestroy, (Sampler->ZeSampler)); + // Gracefully handle the case that L0 was already unloaded. + if (ZeResult && (ZeResult != ZE_RESULT_ERROR_UNINITIALIZED || + ZeResult != ZE_RESULT_ERROR_UNKNOWN)) + return ze2urResult(ZeResult); + if (ZeResult == ZE_RESULT_ERROR_UNKNOWN) { + ZeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } + } delete Sampler; return UR_RESULT_SUCCESS; diff --git a/unified-runtime/source/adapters/level_zero/usm.cpp b/unified-runtime/source/adapters/level_zero/usm.cpp index c3cb6385f3233..15b67f8ce8255 100644 --- a/unified-runtime/source/adapters/level_zero/usm.cpp +++ b/unified-runtime/source/adapters/level_zero/usm.cpp @@ -683,8 +683,7 @@ ur_result_t UR_APICALL urUSMPoolTrimToExp(ur_context_handle_t, static ur_result_t USMFreeImpl(ur_context_handle_t Context, void *Ptr) { ur_result_t Res = UR_RESULT_SUCCESS; - if (!Context->IsInteropNativeHandle || - (Context->IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (checkL0LoaderTeardown()) { auto ZeResult = ZE_CALL_NOCHECK(zeMemFree, (Context->ZeContext, Ptr)); // Handle When the driver is already released if (ZeResult == ZE_RESULT_ERROR_UNINITIALIZED) { diff --git a/unified-runtime/source/adapters/level_zero/v2/common.hpp b/unified-runtime/source/adapters/level_zero/v2/common.hpp index 504a7d6c618ed..23a2495d19b83 100644 --- a/unified-runtime/source/adapters/level_zero/v2/common.hpp +++ b/unified-runtime/source/adapters/level_zero/v2/common.hpp @@ -79,12 +79,15 @@ struct ze_handle_wrapper { return; } - if ((ownZeHandle && !IsInteropNativeHandle) || - (ownZeHandle && IsInteropNativeHandle && checkL0LoaderTeardown())) { + if (ownZeHandle && checkL0LoaderTeardown()) { auto zeResult = destroy(handle); // Gracefully handle the case that L0 was already unloaded. - if (zeResult && zeResult != ZE_RESULT_ERROR_UNINITIALIZED) + if (zeResult && (zeResult != ZE_RESULT_ERROR_UNINITIALIZED || + zeResult != ZE_RESULT_ERROR_UNKNOWN)) throw ze2urResult(zeResult); + if (zeResult == ZE_RESULT_ERROR_UNKNOWN) { + zeResult = ZE_RESULT_ERROR_UNINITIALIZED; + } } handle = nullptr; @@ -103,7 +106,6 @@ struct ze_handle_wrapper { private: ZeHandleT handle; bool ownZeHandle; - bool IsInteropNativeHandle = false; }; using ze_kernel_handle_t = HANDLE_WRAPPER_TYPE(::ze_kernel_handle_t, diff --git a/unified-runtime/source/adapters/level_zero/v2/context.cpp b/unified-runtime/source/adapters/level_zero/v2/context.cpp index 5fe913d878201..33b7f437215b0 100644 --- a/unified-runtime/source/adapters/level_zero/v2/context.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/context.cpp @@ -152,7 +152,6 @@ ur_result_t urContextCreateWithNativeHandle( *phContext = new ur_context_handle_t_(zeContext, numDevices, phDevices, ownZeHandle); - (*phContext)->IsInteropNativeHandle = true; return UR_RESULT_SUCCESS; } catch (...) { return exceptionToResult(std::current_exception()); diff --git a/unified-runtime/source/adapters/level_zero/v2/event.cpp b/unified-runtime/source/adapters/level_zero/v2/event.cpp index 68c0d439dce7d..a26fc1a2a45dd 100644 --- a/unified-runtime/source/adapters/level_zero/v2/event.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/event.cpp @@ -398,7 +398,6 @@ urEventCreateWithNativeHandle(ur_native_handle_t hNativeEvent, ZE2UR_CALL(zeEventHostSignal, ((*phEvent)->getZeEvent())); } else { *phEvent = new ur_event_handle_t_(hContext, hNativeEvent, pProperties); - (*phEvent)->IsInteropNativeHandle = true; } return UR_RESULT_SUCCESS; } catch (...) { diff --git a/unified-runtime/source/adapters/level_zero/v2/kernel.cpp b/unified-runtime/source/adapters/level_zero/v2/kernel.cpp index 5f8bad0acdbc8..6d475552279d8 100644 --- a/unified-runtime/source/adapters/level_zero/v2/kernel.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/kernel.cpp @@ -361,7 +361,6 @@ urKernelCreateWithNativeHandle(ur_native_handle_t hNativeKernel, *phKernel = new ur_kernel_handle_t_(hNativeKernel, hProgram, hContext, pProperties); - (*phKernel)->IsInteropNativeHandle = true; return UR_RESULT_SUCCESS; } catch (...) { return exceptionToResult(std::current_exception()); diff --git a/unified-runtime/source/adapters/level_zero/v2/memory.cpp b/unified-runtime/source/adapters/level_zero/v2/memory.cpp index 63e29df5462eb..d2025da38b62c 100644 --- a/unified-runtime/source/adapters/level_zero/v2/memory.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/memory.cpp @@ -107,17 +107,14 @@ ur_integrated_buffer_handle_t::ur_integrated_buffer_handle_t( ur_integrated_buffer_handle_t::ur_integrated_buffer_handle_t( ur_context_handle_t hContext, void *hostPtr, size_t size, - device_access_mode_t accessMode, bool ownHostPtr, bool interopNativeHandle) + device_access_mode_t accessMode, bool ownHostPtr) : ur_mem_buffer_t(hContext, size, accessMode) { - this->IsInteropNativeHandle = interopNativeHandle; - this->ptr = - usm_unique_ptr_t(hostPtr, [hContext, ownHostPtr, this](void *ptr) { - if (!ownHostPtr || - (this->IsInteropNativeHandle && !checkL0LoaderTeardown())) { - return; - } - ZE_CALL_NOCHECK(zeMemFree, (hContext->getZeHandle(), ptr)); - }); + this->ptr = usm_unique_ptr_t(hostPtr, [hContext, ownHostPtr](void *ptr) { + if (!ownHostPtr || !checkL0LoaderTeardown()) { + return; + } + ZE_CALL_NOCHECK(zeMemFree, (hContext->getZeHandle(), ptr)); + }); } void *ur_integrated_buffer_handle_t::getDevicePtr( @@ -223,7 +220,7 @@ ur_discrete_buffer_handle_t::ur_discrete_buffer_handle_t( ur_discrete_buffer_handle_t::ur_discrete_buffer_handle_t( ur_context_handle_t hContext, ur_device_handle_t hDevice, void *devicePtr, size_t size, device_access_mode_t accessMode, void *writeBackMemory, - bool ownZePtr, bool interopNativeHandle) + bool ownZePtr) : ur_mem_buffer_t(hContext, size, accessMode), deviceAllocations(hContext->getPlatform()->getNumDevices()), activeAllocationDevice(hDevice), writeBackPtr(writeBackMemory), @@ -234,11 +231,9 @@ ur_discrete_buffer_handle_t::ur_discrete_buffer_handle_t( devicePtr = allocateOnDevice(hDevice, size); } else { assert(hDevice); - this->IsInteropNativeHandle = interopNativeHandle; deviceAllocations[hDevice->Id.value()] = usm_unique_ptr_t( - devicePtr, [this, hContext = this->hContext, ownZePtr](void *ptr) { - if (!ownZePtr || - (this->IsInteropNativeHandle && !checkL0LoaderTeardown())) { + devicePtr, [hContext = this->hContext, ownZePtr](void *ptr) { + if (!ownZePtr || !checkL0LoaderTeardown()) { return; } ZE_CALL_NOCHECK(zeMemFree, (hContext->getZeHandle(), ptr)); @@ -468,10 +463,8 @@ ur_mem_image_t::ur_mem_image_t(ur_context_handle_t hContext, ur_mem_image_t::ur_mem_image_t(ur_context_handle_t hContext, const ur_image_format_t *pImageFormat, const ur_image_desc_t *pImageDesc, - ze_image_handle_t zeImage, bool ownZeImage, - bool interopNativeHandle) + ze_image_handle_t zeImage, bool ownZeImage) : hContext(hContext), zeImage(zeImage, ownZeImage) { - this->IsInteropNativeHandle = interopNativeHandle; UR_CALL_THROWS(ur2zeImageDesc(pImageFormat, pImageDesc, zeImageDesc)); } @@ -613,7 +606,7 @@ ur_result_t urMemBufferCreateWithNativeHandle( if (useHostBuffer(hContext) && memoryAttrs.type == ZE_MEMORY_TYPE_HOST) { *phMem = ur_mem_handle_t_::create( - hContext, ptr, size, accessMode, ownNativeHandle, true); + hContext, ptr, size, accessMode, ownNativeHandle); // if useHostBuffer(hContext) is true but the allocation is on device, we'll // treat it as discrete memory } else if (memoryAttrs.type == ZE_MEMORY_TYPE_SHARED) { @@ -625,14 +618,12 @@ ur_result_t urMemBufferCreateWithNativeHandle( // For host allocation, we need to copy the data to a device buffer // and then copy it back on release *phMem = ur_mem_handle_t_::create( - hContext, hDevice, nullptr, size, accessMode, ptr, ownNativeHandle, - true); + hContext, hDevice, nullptr, size, accessMode, ptr, ownNativeHandle); } else { // For device allocation, we can use it directly assert(hDevice); *phMem = ur_mem_handle_t_::create( - hContext, hDevice, ptr, size, accessMode, nullptr, ownNativeHandle, - true); + hContext, hDevice, ptr, size, accessMode, nullptr, ownNativeHandle); } } @@ -742,7 +733,7 @@ ur_result_t urMemImageCreateWithNativeHandle( bool ownNativeHandle = pProperties ? pProperties->isNativeHandleOwned : false; *phMem = ur_mem_handle_t_::create( - hContext, pImageFormat, pImageDesc, zeImage, ownNativeHandle, true); + hContext, pImageFormat, pImageDesc, zeImage, ownNativeHandle); return UR_RESULT_SUCCESS; } catch (...) { return exceptionToResult(std::current_exception()); diff --git a/unified-runtime/source/adapters/level_zero/v2/memory.hpp b/unified-runtime/source/adapters/level_zero/v2/memory.hpp index 28f78bdc15915..f616b7c67f953 100644 --- a/unified-runtime/source/adapters/level_zero/v2/memory.hpp +++ b/unified-runtime/source/adapters/level_zero/v2/memory.hpp @@ -20,8 +20,6 @@ using usm_unique_ptr_t = std::unique_ptr>; struct ur_mem_buffer_t : _ur_object { - // Indicates if this object is an interop handle. - bool IsInteropNativeHandle = false; enum class device_access_mode_t { read_write, read_only, write_only }; @@ -85,7 +83,7 @@ struct ur_integrated_buffer_handle_t : ur_mem_buffer_t { ur_integrated_buffer_handle_t(ur_context_handle_t hContext, void *hostPtr, size_t size, device_access_mode_t accesMode, - bool ownHostPtr, bool interopNativeHandle); + bool ownHostPtr); void * getDevicePtr(ur_device_handle_t, device_access_mode_t, size_t offset, @@ -125,8 +123,7 @@ struct ur_discrete_buffer_handle_t : ur_mem_buffer_t { ur_discrete_buffer_handle_t(ur_context_handle_t hContext, ur_device_handle_t hDevice, void *devicePtr, size_t size, device_access_mode_t accesMode, - void *writeBackMemory, bool ownDevicePtr, - bool interopNativeHandle); + void *writeBackMemory, bool ownDevicePtr); void * getDevicePtr(ur_device_handle_t, device_access_mode_t, size_t offset, @@ -206,7 +203,7 @@ struct ur_mem_image_t : _ur_object { const ur_image_desc_t *pImageDesc, void *pHost); ur_mem_image_t(ur_context_handle_t, const ur_image_format_t *pImageFormat, const ur_image_desc_t *pImageDesc, ze_image_handle_t zeImage, - bool ownZeImage, bool interopNativeHandle); + bool ownZeImage); ze_image_handle_t getZeImage() const { return zeImage.get(); } diff --git a/unified-runtime/source/adapters/level_zero/v2/queue_create.cpp b/unified-runtime/source/adapters/level_zero/v2/queue_create.cpp index 9f45404b7e39d..7e2de8b1b647b 100644 --- a/unified-runtime/source/adapters/level_zero/v2/queue_create.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/queue_create.cpp @@ -59,7 +59,7 @@ ur_result_t urQueueCreateWithNativeHandle( } *phQueue = ur_queue_handle_t_::create( - hContext, hDevice, hNativeQueue, flags, ownNativeHandle, true); + hContext, hDevice, hNativeQueue, flags, ownNativeHandle); return UR_RESULT_SUCCESS; } catch (...) { diff --git a/unified-runtime/source/adapters/level_zero/v2/queue_handle.hpp b/unified-runtime/source/adapters/level_zero/v2/queue_handle.hpp index 26b58c9c6c4cd..a17d304ea5cfc 100644 --- a/unified-runtime/source/adapters/level_zero/v2/queue_handle.hpp +++ b/unified-runtime/source/adapters/level_zero/v2/queue_handle.hpp @@ -49,6 +49,4 @@ struct ur_queue_handle_t_ { }, queue_data); } - // Indicates if this object is an interop handle. - bool IsInteropNativeHandle = false; }; diff --git a/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.cpp b/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.cpp index 7646b48bfc6dc..07eb5381a48c6 100644 --- a/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.cpp @@ -77,17 +77,15 @@ ur_queue_immediate_in_order_t::ur_queue_immediate_in_order_t( ur_queue_immediate_in_order_t::ur_queue_immediate_in_order_t( ur_context_handle_t hContext, ur_device_handle_t hDevice, - ur_native_handle_t hNativeHandle, ur_queue_flags_t flags, bool ownZeQueue, - bool interopNativeHandle) + ur_native_handle_t hNativeHandle, ur_queue_flags_t flags, bool ownZeQueue) : hContext(hContext), hDevice(hDevice), flags(flags), commandListManager( hContext, hDevice, raii::command_list_unique_handle( reinterpret_cast(hNativeHandle), - [ownZeQueue, - interopNativeHandle](ze_command_list_handle_t hZeCommandList) { + [ownZeQueue](ze_command_list_handle_t hZeCommandList) { if (ownZeQueue) { - if (!interopNativeHandle) { + if (checkL0LoaderTeardown()) { ZE_CALL_NOCHECK(zeCommandListDestroy, (hZeCommandList)); } } diff --git a/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.hpp b/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.hpp index 75fd7aba89b2f..7ddd96fd9ff91 100644 --- a/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.hpp +++ b/unified-runtime/source/adapters/level_zero/v2/queue_immediate_in_order.hpp @@ -72,7 +72,7 @@ struct ur_queue_immediate_in_order_t : _ur_object, public ur_queue_t_ { const ur_queue_properties_t *); ur_queue_immediate_in_order_t(ur_context_handle_t, ur_device_handle_t, ur_native_handle_t, ur_queue_flags_t, - bool ownZeQueue, bool interopNativeHandle); + bool ownZeQueue); ~ur_queue_immediate_in_order_t();