From 21076b57df4a46927748be85dc310f8ea9403749 Mon Sep 17 00:00:00 2001 From: Bartosz Dunajski Date: Wed, 6 Aug 2025 17:01:47 +0000 Subject: [PATCH] fix: ensure queue completion on destruction Related-To: HSD-22021388724 Signed-off-by: Bartosz Dunajski --- opencl/source/command_queue/command_queue.cpp | 4 +++ opencl/source/command_queue/command_queue.h | 2 ++ opencl/source/helpers/queue_helpers.h | 6 +++- .../command_queue/command_queue_tests.cpp | 30 +++++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/opencl/source/command_queue/command_queue.cpp b/opencl/source/command_queue/command_queue.cpp index 5265beca65..6f35137fa1 100644 --- a/opencl/source/command_queue/command_queue.cpp +++ b/opencl/source/command_queue/command_queue.cpp @@ -449,6 +449,10 @@ void CommandQueue::releaseMainCopyEngine() { } } +bool CommandQueue::waitOnDestructionNeeded() const { + return (device && (getRefApiCount() == 1) && (taskCount < CompletionStamp::notReady)); +} + Device &CommandQueue::getDevice() const noexcept { return device->getDevice(); } diff --git a/opencl/source/command_queue/command_queue.h b/opencl/source/command_queue/command_queue.h index 38f6d058fc..a320419ee7 100644 --- a/opencl/source/command_queue/command_queue.h +++ b/opencl/source/command_queue/command_queue.h @@ -433,6 +433,8 @@ class CommandQueue : public BaseObject<_cl_command_queue> { return retVal; } + bool waitOnDestructionNeeded() const; + protected: void *enqueueReadMemObjForMap(TransferProperties &transferProperties, EventsRequest &eventsRequest, cl_int &errcodeRet); cl_int enqueueWriteMemObjForUnmap(MemObj *memObj, void *mappedPtr, EventsRequest &eventsRequest); diff --git a/opencl/source/helpers/queue_helpers.h b/opencl/source/helpers/queue_helpers.h index ff7b8ff187..a7f54c55ed 100644 --- a/opencl/source/helpers/queue_helpers.h +++ b/opencl/source/helpers/queue_helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -52,6 +52,10 @@ inline void releaseQueue(cl_command_queue commandQueue, cl_int &retVal) { if (queue) { queue->flush(); releaseVirtualEvent(*queue); + + if (queue->waitOnDestructionNeeded()) { + queue->waitForAllEngines(false, nullptr, true, false); + } queue->release(); retVal = CL_SUCCESS; } diff --git a/opencl/test/unit_test/command_queue/command_queue_tests.cpp b/opencl/test/unit_test/command_queue/command_queue_tests.cpp index bdda181f40..f302b85798 100644 --- a/opencl/test/unit_test/command_queue/command_queue_tests.cpp +++ b/opencl/test/unit_test/command_queue/command_queue_tests.cpp @@ -141,6 +141,36 @@ TEST(CommandQueue, WhenGettingErrorCodeFromTaskCountThenProperValueIsReturned) { EXPECT_EQ(CL_OUT_OF_RESOURCES, CommandQueue::getErrorCodeFromTaskCount(CompletionStamp::failed)); } +TEST(CommandQueue, givenCommandQueueWhenDestructedThenWaitForAllEngines) { + uint32_t waitCalled = 0; + + class MyMockCommandQueue : public MockCommandQueue { + public: + MyMockCommandQueue(uint32_t &waitCalled, Context *context, ClDevice *device) + : MockCommandQueue(context, device, nullptr, false), waitCalled(waitCalled) { + } + + MOCKABLE_VIRTUAL WaitStatus waitForAllEngines(bool blockedQueue, PrintfHandler *printfHandler, bool cleanTemporaryAllocationsList, bool waitForTaskCountRequired) { + waitCalled++; + return WaitStatus::ready; + } + + uint32_t &waitCalled; + }; + + auto mockDevice = std::make_unique(MockDevice::createWithNewExecutionEnvironment(nullptr)); + MockContext context(mockDevice.get()); + + auto cmdQ = new MyMockCommandQueue(waitCalled, &context, mockDevice.get()); + EXPECT_EQ(0u, waitCalled); + + cl_int retVal = CL_SUCCESS; + releaseQueue(cmdQ, retVal); + + EXPECT_EQ(1u, waitCalled); + EXPECT_EQ(CL_SUCCESS, retVal); +} + TEST(CommandQueue, GivenCommandQueueWhenIsBcsIsCalledThenIsCopyOnlyIsReturned) { MockCommandQueue cmdQ(nullptr, nullptr, 0, false); EXPECT_EQ(cmdQ.isBcs(), cmdQ.isCopyOnly);