diff --git a/runtime/command_queue/command_queue.cpp b/runtime/command_queue/command_queue.cpp index c49e79fd29..3c3204d97a 100644 --- a/runtime/command_queue/command_queue.cpp +++ b/runtime/command_queue/command_queue.cpp @@ -146,11 +146,6 @@ bool CommandQueue::isQueueBlocked() { UNRECOVERABLE_IF(this->virtualEvent == nullptr); if (this->virtualEvent->isStatusCompletedByTermination(executionStatus) == false) { - //it may happen that virtual event is submitted but doesn't have task count assigned yet - if (this->virtualEvent->peekTaskCount() == Event::eventNotReady) { - return true; - } - taskCount = this->virtualEvent->peekTaskCount(); flushStamp->setStamp(this->virtualEvent->flushStamp->peekStamp()); taskLevel = this->virtualEvent->taskLevel; diff --git a/runtime/event/event.cpp b/runtime/event/event.cpp index e111198f61..6093385627 100644 --- a/runtime/event/event.cpp +++ b/runtime/event/event.cpp @@ -505,6 +505,10 @@ void Event::submitCommand(bool abortTasks) { updateTaskCount(this->cmdQueue->getCommandStreamReceiver().peekTaskCount()); } } + //make sure that task count is synchronized for events with kernels + if (!this->eventWithoutCommand && !abortTasks) { + this->synchronizeTaskCount(); + } } } diff --git a/runtime/event/event.h b/runtime/event/event.h index aacecc2a5e..b8e57d46f4 100644 --- a/runtime/event/event.h +++ b/runtime/event/event.h @@ -325,6 +325,10 @@ class Event : public BaseObject<_cl_event>, public IDNode { bool calcProfilingData(); MOCKABLE_VIRTUAL void calculateProfilingDataInternal(uint64_t contextStartTS, uint64_t contextEndTS, uint64_t *contextCompleteTS, uint64_t globalStartTS); + MOCKABLE_VIRTUAL void synchronizeTaskCount() { + while (this->taskCount == Event::eventNotReady) + ; + }; // executes all callbacks associated with this event void executeCallbacks(int32_t executionStatus); diff --git a/unit_tests/command_queue/command_queue_hw_tests.cpp b/unit_tests/command_queue/command_queue_hw_tests.cpp index 7960b51e43..45edef36d2 100644 --- a/unit_tests/command_queue/command_queue_hw_tests.cpp +++ b/unit_tests/command_queue/command_queue_hw_tests.cpp @@ -753,19 +753,38 @@ HWTEST_F(CommandQueueHwTest, givenCommandQueueThatIsBlockedAndUsesCpuCopyWhenEve clReleaseEvent(returnEvent); } -HWTEST_F(CommandQueueHwTest, givenEventWithRecordedCommandWhenSubmitCommandIsCalledThenTaskCountIsNotUpdated) { +HWTEST_F(CommandQueueHwTest, givenEventWithRecordedCommandWhenSubmitCommandIsCalledThenTaskCountMustBeUpdatedFromOtherThread) { + std::atomic_bool go{false}; + struct mockEvent : public Event { using Event::Event; using Event::eventWithoutCommand; using Event::submitCommand; + void synchronizeTaskCount() override { + *atomicFence = true; + Event::synchronizeTaskCount(); + } + uint32_t synchronizeCallCount = 0u; + std::atomic_bool *atomicFence = nullptr; }; mockEvent neoEvent(this->pCmdQ, CL_COMMAND_MAP_BUFFER, Event::eventNotReady, Event::eventNotReady); + neoEvent.atomicFence = &go; EXPECT_TRUE(neoEvent.eventWithoutCommand); neoEvent.eventWithoutCommand = false; - neoEvent.submitCommand(false); EXPECT_EQ(Event::eventNotReady, neoEvent.peekTaskCount()); + + std::thread t([&]() { + while (!go) + ; + neoEvent.updateTaskCount(77u); + }); + + neoEvent.submitCommand(false); + + EXPECT_EQ(77u, neoEvent.peekTaskCount()); + t.join(); } HWTEST_F(CommandQueueHwTest, GivenBuiltinKernelWhenBuiltinDispatchInfoBuilderIsProvidedThenThisBuilderIsUsedForCreatingDispatchInfo) { diff --git a/unit_tests/event/user_events_tests_mt.cpp b/unit_tests/event/user_events_tests_mt.cpp index 63817f1013..44f471b851 100644 --- a/unit_tests/event/user_events_tests_mt.cpp +++ b/unit_tests/event/user_events_tests_mt.cpp @@ -120,6 +120,7 @@ TEST_F(EventTests, givenoneThreadUpdatingUserEventAnotherWaitingOnFinishWhenFini cl_event returnedEvent = nullptr; std::atomic_bool go{false}; + std::atomic_bool updateEvent{true}; std::thread t([&]() { while (!go) @@ -132,7 +133,9 @@ TEST_F(EventTests, givenoneThreadUpdatingUserEventAnotherWaitingOnFinishWhenFini EXPECT_EQ(CL_SUCCESS, retVal); std::thread t2([&]() { - castToObject(returnedEvent)->updateExecutionStatus(); + while (updateEvent) { + castToObject(returnedEvent)->updateExecutionStatus(); + } }); go = true; @@ -141,6 +144,7 @@ TEST_F(EventTests, givenoneThreadUpdatingUserEventAnotherWaitingOnFinishWhenFini EXPECT_EQ(pCmdQ->latestTaskCountWaited, i + 1); t.join(); + updateEvent = false; t2.join(); clReleaseEvent(returnedEvent); }