diff --git a/runtime/command_stream/command_stream_receiver.h b/runtime/command_stream/command_stream_receiver.h index 5311879526..91dfc1cfe0 100644 --- a/runtime/command_stream/command_stream_receiver.h +++ b/runtime/command_stream/command_stream_receiver.h @@ -145,7 +145,7 @@ class CommandStreamReceiver { void setExperimentalCmdBuffer(std::unique_ptr &&cmdBuffer); bool initializeTagAllocation(); - std::unique_lock obtainUniqueOwnership(); + MOCKABLE_VIRTUAL std::unique_lock obtainUniqueOwnership(); KmdNotifyHelper *peekKmdNotifyHelper() { return kmdNotifyHelper.get(); diff --git a/unit_tests/event/event_tests.cpp b/unit_tests/event/event_tests.cpp index 3140c3de04..9d8e122ebb 100644 --- a/unit_tests/event/event_tests.cpp +++ b/unit_tests/event/event_tests.cpp @@ -864,6 +864,61 @@ TEST(Event, GivenNoContextOnDeletionDeletesSelf) { ASSERT_TRUE(autoptr.isUnused()); } +HWTEST_F(EventTest, givenVirtualEventWhenCommandSubmittedThenLockCSROccurs) { + using UniqueIH = std::unique_ptr; + class MockCommandComputeKernel : public CommandComputeKernel { + public: + using CommandComputeKernel::eventsWaitlist; + MockCommandComputeKernel(CommandQueue &commandQueue, KernelOperation *kernelResources, std::vector &surfaces, Kernel *kernel) + : CommandComputeKernel(commandQueue, std::unique_ptr(kernelResources), surfaces, false, false, false, nullptr, PreemptionMode::Disabled, kernel, 0) {} + }; + class MockEvent : public Event { + public: + using Event::submitCommand; + MockEvent(CommandQueue *cmdQueue, cl_command_type cmdType, + uint32_t taskLevel, uint32_t taskCount) : Event(cmdQueue, cmdType, + taskLevel, taskCount) {} + }; + + MockKernelWithInternals kernel(*pDevice); + + IndirectHeap *ih1 = nullptr, *ih2 = nullptr, *ih3 = nullptr; + pCmdQ->allocateHeapMemory(IndirectHeap::DYNAMIC_STATE, 1, ih1); + pCmdQ->allocateHeapMemory(IndirectHeap::INDIRECT_OBJECT, 1, ih2); + pCmdQ->allocateHeapMemory(IndirectHeap::SURFACE_STATE, 1, ih3); + auto cmdStream = new LinearStream(alignedMalloc(1, 1), 1); + + std::vector surfaces; + auto kernelOperation = new KernelOperation(std::unique_ptr(cmdStream), UniqueIH(ih1), UniqueIH(ih2), UniqueIH(ih3), + *pDevice->getDefaultEngine().commandStreamReceiver->getInternalAllocationStorage()); + + std::unique_ptr command = std::make_unique(*pCmdQ, kernelOperation, surfaces, kernel); + + auto virtualEvent = make_releaseable(pCmdQ, CL_COMMAND_NDRANGE_KERNEL, Event::eventNotReady, Event::eventNotReady); + + virtualEvent->setCommand(std::move(command)); + + virtualEvent->submitCommand(false); + + EXPECT_EQ(pDevice->getUltCommandStreamReceiver().recursiveLockCounter, 2u); +} + +HWTEST_F(EventTest, givenVirtualEventWhenSubmitCommandEventNotReadyAndEventWithoutCommandThenOneLockCSRNeeded) { + class MockEvent : public Event { + public: + using Event::submitCommand; + MockEvent(CommandQueue *cmdQueue, cl_command_type cmdType, + uint32_t taskLevel, uint32_t taskCount) : Event(cmdQueue, cmdType, + taskLevel, taskCount) {} + }; + + auto virtualEvent = make_releaseable(pCmdQ, CL_COMMAND_NDRANGE_KERNEL, Event::eventNotReady, Event::eventNotReady); + + virtualEvent->submitCommand(false); + + EXPECT_EQ(pDevice->getUltCommandStreamReceiver().recursiveLockCounter, 1u); +} + HWTEST_F(InternalsEventTest, GivenBufferWithoutZeroCopyOnCommandMapOrUnmapFlushesPreviousTasksBeforeMappingOrUnmapping) { struct MockNonZeroCopyBuff : UnalignedBuffer { MockNonZeroCopyBuff(int32_t &executionStamp) diff --git a/unit_tests/libult/ult_command_stream_receiver.h b/unit_tests/libult/ult_command_stream_receiver.h index 0b386b2319..79c2cffcab 100644 --- a/unit_tests/libult/ult_command_stream_receiver.h +++ b/unit_tests/libult/ult_command_stream_receiver.h @@ -68,7 +68,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ } } - UltCommandStreamReceiver(const HardwareInfo &hwInfoIn, ExecutionEnvironment &executionEnvironment) : BaseClass(hwInfoIn, executionEnvironment) { + UltCommandStreamReceiver(const HardwareInfo &hwInfoIn, ExecutionEnvironment &executionEnvironment) : BaseClass(hwInfoIn, executionEnvironment), recursiveLockCounter(0) { if (hwInfoIn.capabilityTable.defaultPreemptionMode == PreemptionMode::MidThread) { tempPreemptionLocation = std::make_unique(nullptr, 0, 0, 0, false); this->preemptionCsrAllocation = tempPreemptionLocation.get(); @@ -129,6 +129,12 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ initProgrammingFlagsCalled = true; } + std::unique_lock obtainUniqueOwnership() override { + recursiveLockCounter++; + return CommandStreamReceiverHw::obtainUniqueOwnership(); + } + + std::atomic recursiveLockCounter; bool createPageTableManagerCalled = false; bool activateAubSubCaptureCalled = false; bool flushBatchedSubmissionsCalled = false;