From fc37272efb73c2db26e1797d960a8b5ab79b52cd Mon Sep 17 00:00:00 2001 From: "Zhang, Winston" Date: Mon, 21 Jul 2025 12:11:49 -0700 Subject: [PATCH 1/3] [UR][L0] Event pool cache leak fix Addresses event pool leak when SYCL_PI_LEVEL_ZERO_DISABLE_EVENTS_CACHING is set. Improper cleanup in getFreeSlotInExistingOrNewPool. Signed-off-by: Zhang, Winston --- unified-runtime/source/adapters/level_zero/context.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unified-runtime/source/adapters/level_zero/context.cpp b/unified-runtime/source/adapters/level_zero/context.cpp index fe690f3673934..adf80f83dc75c 100644 --- a/unified-runtime/source/adapters/level_zero/context.cpp +++ b/unified-runtime/source/adapters/level_zero/context.cpp @@ -423,6 +423,9 @@ ur_result_t ur_context_handle_t_::getFreeSlotInExistingOrNewPool( if (NumEventsAvailableInEventPool[ZePoolCache->front()] == 0) { if (DisableEventsCaching) { // Remove full pool from the cache if events caching is disabled. + for (auto &ZePool : *ZePoolCache) { + ZE_CALL_NOCHECK(zeEventPoolDestroy, (ZePool)); + } ZePoolCache->erase(ZePoolCache->begin()); } else { // If event caching is enabled then we don't destroy events so there is From 76f16e3f7056e5d32cdf195be39becf3af69c959 Mon Sep 17 00:00:00 2001 From: "Zhang, Winston" Date: Tue, 22 Jul 2025 10:54:31 -0700 Subject: [PATCH 2/3] [UR][L0] zeEventPoolDestroy on the first element on ZePoolCache Signed-off-by: Zhang, Winston --- unified-runtime/source/adapters/level_zero/context.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/unified-runtime/source/adapters/level_zero/context.cpp b/unified-runtime/source/adapters/level_zero/context.cpp index adf80f83dc75c..26545fcff4c9f 100644 --- a/unified-runtime/source/adapters/level_zero/context.cpp +++ b/unified-runtime/source/adapters/level_zero/context.cpp @@ -423,9 +423,7 @@ ur_result_t ur_context_handle_t_::getFreeSlotInExistingOrNewPool( if (NumEventsAvailableInEventPool[ZePoolCache->front()] == 0) { if (DisableEventsCaching) { // Remove full pool from the cache if events caching is disabled. - for (auto &ZePool : *ZePoolCache) { - ZE_CALL_NOCHECK(zeEventPoolDestroy, (ZePool)); - } + ZE_CALL_NOCHECK(zeEventPoolDestroy, (ZePoolCache->front())); ZePoolCache->erase(ZePoolCache->begin()); } else { // If event caching is enabled then we don't destroy events so there is From fa1c9d6fd7cfa6eb8a212d362483de1600fd1505 Mon Sep 17 00:00:00 2001 From: "Zhang, Winston" Date: Mon, 28 Jul 2025 18:48:39 -0700 Subject: [PATCH 3/3] fixed segfault during zeEventPoolCreate Signed-off-by: Zhang, Winston --- .../source/adapters/level_zero/context.cpp | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/unified-runtime/source/adapters/level_zero/context.cpp b/unified-runtime/source/adapters/level_zero/context.cpp index 26545fcff4c9f..930b57f3546a1 100644 --- a/unified-runtime/source/adapters/level_zero/context.cpp +++ b/unified-runtime/source/adapters/level_zero/context.cpp @@ -407,14 +407,71 @@ ur_result_t ur_context_handle_t_::getFreeSlotInExistingOrNewPool( bool ProfilingEnabled, ur_device_handle_t Device, bool CounterBasedEventEnabled, bool UsingImmCmdList, bool InterruptBasedEventEnabled) { - // Lock while updating event pool machinery. - std::scoped_lock Lock(ZeEventPoolCacheMutex); ze_device_handle_t ZeDevice = nullptr; - if (Device) { ZeDevice = Device->ZeDevice; } + + if (DisableEventsCaching) { + // Skip all cache handling, always create a new pool + ze_event_pool_counter_based_exp_desc_t counterBasedExt = { + ZE_STRUCTURE_TYPE_COUNTER_BASED_EVENT_POOL_EXP_DESC, nullptr, 0}; + + ze_intel_event_sync_mode_exp_desc_t eventSyncMode = { + ZE_INTEL_STRUCTURE_TYPE_EVENT_SYNC_MODE_EXP_DESC, nullptr, 0}; + eventSyncMode.syncModeFlags = + ZE_INTEL_EVENT_SYNC_MODE_EXP_FLAG_LOW_POWER_WAIT | + ZE_INTEL_EVENT_SYNC_MODE_EXP_FLAG_SIGNAL_INTERRUPT; + + ZeStruct ZeEventPoolDesc; + ZeEventPoolDesc.count = MaxNumEventsPerPool; + ZeEventPoolDesc.flags = 0; + ZeEventPoolDesc.pNext = nullptr; + if (HostVisible) + ZeEventPoolDesc.flags |= ZE_EVENT_POOL_FLAG_HOST_VISIBLE; + if (ProfilingEnabled) + ZeEventPoolDesc.flags |= ZE_EVENT_POOL_FLAG_KERNEL_TIMESTAMP; + UR_LOG(DEBUG, "ze_event_pool_desc_t flags set to: {}", + ZeEventPoolDesc.flags); + if (CounterBasedEventEnabled) { + if (UsingImmCmdList) { + counterBasedExt.flags = ZE_EVENT_POOL_COUNTER_BASED_EXP_FLAG_IMMEDIATE; + } else { + counterBasedExt.flags = + ZE_EVENT_POOL_COUNTER_BASED_EXP_FLAG_NON_IMMEDIATE; + } + UR_LOG(DEBUG, "ze_event_pool_desc_t counter based flags set to: {}", + counterBasedExt.flags); + if (InterruptBasedEventEnabled) { + counterBasedExt.pNext = &eventSyncMode; + } + ZeEventPoolDesc.pNext = &counterBasedExt; + } else if (InterruptBasedEventEnabled) { + ZeEventPoolDesc.pNext = &eventSyncMode; + } + + std::vector ZeDevices; + if (ZeDevice) { + ZeDevices.push_back(ZeDevice); + } else { + std::for_each(Devices.begin(), Devices.end(), + [&](const ur_device_handle_t &D) { + ZeDevices.push_back(D->ZeDevice); + }); + } + + ZE2UR_CALL(zeEventPoolCreate, (ZeContext, &ZeEventPoolDesc, + ZeDevices.size(), &ZeDevices[0], &Pool)); + Index = 0; + NumEventsAvailableInEventPool[Pool] = MaxNumEventsPerPool - 1; + NumEventsUnreleasedInEventPool[Pool] = 1; + return UR_RESULT_SUCCESS; + } + + // --- Normal cache-based logic below --- + std::scoped_lock Lock(ZeEventPoolCacheMutex); + std::list *ZePoolCache = getZeEventPoolCache( HostVisible, ProfilingEnabled, CounterBasedEventEnabled, UsingImmCmdList, InterruptBasedEventEnabled, ZeDevice);