From a6d898a026b2d44a5dd05b827f70486836fc9407 Mon Sep 17 00:00:00 2001 From: Mateusz Jablonski Date: Sat, 6 Feb 2021 14:38:55 +0000 Subject: [PATCH] Improve GPU breakpoint support handle user confirmations in gpu modes: always, only before, only after handle multiple confirmations when pausing on each enqueue Signed-off-by: Mateusz Jablonski --- .../command_stream_receiver_tests.cpp | 176 +++++++++++++++++- .../command_stream_receiver.cpp | 81 ++++---- 2 files changed, 217 insertions(+), 40 deletions(-) diff --git a/opencl/test/unit_test/command_stream/command_stream_receiver_tests.cpp b/opencl/test/unit_test/command_stream/command_stream_receiver_tests.cpp index 10124f733e..135ebb3659 100644 --- a/opencl/test/unit_test/command_stream/command_stream_receiver_tests.cpp +++ b/opencl/test/unit_test/command_stream/command_stream_receiver_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -1175,6 +1175,180 @@ HWTEST_F(CommandStreamReceiverTest, givenDebugPauseThreadWhenSettingFlagProgress EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Workload ended, press enter to continue"))); } +HWTEST_F(CommandStreamReceiverTest, givenDebugPauseThreadBeforeWalkerOnlyWhenSettingFlagProgressThenFunctionAsksOnceForConfirmation) { + DebugManagerStateRestore restore; + DebugManager.flags.PauseOnEnqueue.set(0); + DebugManager.flags.PauseOnGpuMode.set(0); + testing::internal::CaptureStdout(); + int32_t executionStamp = 0; + auto mockCSR = new MockCsr(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex(), pDevice->getDeviceBitfield()); + + uint32_t confirmationCounter = 0; + + mockCSR->debugConfirmationFunction = [&confirmationCounter, &mockCSR]() { + EXPECT_EQ(0u, confirmationCounter); + EXPECT_TRUE(DebugPauseState::waitingForUserStartConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + }; + + pDevice->resetCommandStreamReceiver(mockCSR); + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserStartConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserStartConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + EXPECT_EQ(1u, confirmationCounter); + + auto output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Press enter to start workload"))); + EXPECT_THAT(output, testing::Not(testing::HasSubstr(std::string("Debug break: Workload ended, press enter to continue")))); +} + +HWTEST_F(CommandStreamReceiverTest, givenDebugPauseThreadAfterWalkerOnlyWhenSettingFlagProgressThenFunctionAsksOnceForConfirmation) { + DebugManagerStateRestore restore; + DebugManager.flags.PauseOnEnqueue.set(0); + DebugManager.flags.PauseOnGpuMode.set(1); + testing::internal::CaptureStdout(); + int32_t executionStamp = 0; + auto mockCSR = new MockCsr(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex(), pDevice->getDeviceBitfield()); + + uint32_t confirmationCounter = 0; + + mockCSR->debugConfirmationFunction = [&confirmationCounter, &mockCSR]() { + EXPECT_EQ(0u, confirmationCounter); + EXPECT_TRUE(DebugPauseState::waitingForUserEndConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + }; + + pDevice->resetCommandStreamReceiver(mockCSR); + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserEndConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + EXPECT_EQ(1u, confirmationCounter); + + auto output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, testing::Not(testing::HasSubstr(std::string("Debug break: Press enter to start workload")))); + EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Workload ended, press enter to continue"))); +} + +HWTEST_F(CommandStreamReceiverTest, givenDebugPauseThreadOnEachEnqueueWhenSettingFlagProgressThenFunctionAsksMultipleTimesForConfirmation) { + DebugManagerStateRestore restore; + DebugManager.flags.PauseOnEnqueue.set(-2); + testing::internal::CaptureStdout(); + int32_t executionStamp = 0; + auto mockCSR = new MockCsr(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex(), pDevice->getDeviceBitfield()); + + uint32_t confirmationCounter = 0; + + mockCSR->debugConfirmationFunction = [&confirmationCounter, &mockCSR]() { + if (confirmationCounter == 0) { + EXPECT_TRUE(DebugPauseState::waitingForUserStartConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + } else if (confirmationCounter == 1) { + EXPECT_TRUE(DebugPauseState::waitingForUserEndConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + } else if (confirmationCounter == 2) { + EXPECT_TRUE(DebugPauseState::waitingForUserStartConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + } else if (confirmationCounter == 3) { + EXPECT_TRUE(DebugPauseState::waitingForUserEndConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + DebugManager.flags.PauseOnEnqueue.set(-1); + } + }; + + pDevice->resetCommandStreamReceiver(mockCSR); + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserStartConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserStartConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserEndConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserStartConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserStartConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserEndConfirmation) + ; + + EXPECT_EQ(4u, confirmationCounter); + + auto output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Press enter to start workload"))); + EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Workload ended, press enter to continue"))); +} + +HWTEST_F(CommandStreamReceiverTest, givenDebugPauseThreadOnEachBlitWhenSettingFlagProgressThenFunctionAsksMultipleTimesForConfirmation) { + DebugManagerStateRestore restore; + DebugManager.flags.PauseOnBlitCopy.set(-2); + testing::internal::CaptureStdout(); + int32_t executionStamp = 0; + auto mockCSR = new MockCsr(executionStamp, *pDevice->executionEnvironment, pDevice->getRootDeviceIndex(), pDevice->getDeviceBitfield()); + + uint32_t confirmationCounter = 0; + + mockCSR->debugConfirmationFunction = [&confirmationCounter, &mockCSR]() { + if (confirmationCounter == 0) { + EXPECT_TRUE(DebugPauseState::waitingForUserStartConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + } else if (confirmationCounter == 1) { + EXPECT_TRUE(DebugPauseState::waitingForUserEndConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + } else if (confirmationCounter == 2) { + EXPECT_TRUE(DebugPauseState::waitingForUserStartConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + } else if (confirmationCounter == 3) { + EXPECT_TRUE(DebugPauseState::waitingForUserEndConfirmation == *mockCSR->debugPauseStateAddress); + confirmationCounter++; + DebugManager.flags.PauseOnBlitCopy.set(-1); + } + }; + + pDevice->resetCommandStreamReceiver(mockCSR); + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserStartConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserStartConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserEndConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserStartConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserStartConfirmation) + ; + + *mockCSR->debugPauseStateAddress = DebugPauseState::waitingForUserEndConfirmation; + + while (*mockCSR->debugPauseStateAddress != DebugPauseState::hasUserEndConfirmation) + ; + + EXPECT_EQ(4u, confirmationCounter); + + auto output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Press enter to start workload"))); + EXPECT_THAT(output, testing::HasSubstr(std::string("Debug break: Workload ended, press enter to continue"))); +} + HWTEST_F(CommandStreamReceiverTest, givenDebugPauseThreadWhenTerminatingAtFirstStageThenFunctionEndsCorrectly) { DebugManagerStateRestore restore; DebugManager.flags.PauseOnEnqueue.set(0); diff --git a/shared/source/command_stream/command_stream_receiver.cpp b/shared/source/command_stream/command_stream_receiver.cpp index dcb2b9e029..9a64313d7c 100644 --- a/shared/source/command_stream/command_stream_receiver.cpp +++ b/shared/source/command_stream/command_stream_receiver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -17,6 +17,7 @@ #include "shared/source/helpers/cache_policy.h" #include "shared/source/helpers/flush_stamp.h" #include "shared/source/helpers/hw_helper.h" +#include "shared/source/helpers/pause_on_gpu_properties.h" #include "shared/source/helpers/string.h" #include "shared/source/helpers/timestamp_packet.h" #include "shared/source/memory_manager/internal_allocation_storage.h" @@ -408,48 +409,50 @@ void CommandStreamReceiver::setExperimentalCmdBuffer(std::unique_ptr(arg); - auto debugPauseStateValue = DebugPauseState::waitingForUserStartConfirmation; - do { - { - std::unique_lock lock{self->debugPauseStateLock}; - debugPauseStateValue = *self->debugPauseStateAddress; + auto debugPauseStateValue = DebugPauseState::waitingForUserStartConfirmation; + if (DebugManager.flags.PauseOnGpuMode.get() != PauseOnGpuProperties::PauseMode::AfterWorkload) { + do { + { + std::unique_lock lock{self->debugPauseStateLock}; + debugPauseStateValue = *self->debugPauseStateAddress; + } + + if (debugPauseStateValue == DebugPauseState::terminate) { + return nullptr; + } + std::this_thread::yield(); + } while (debugPauseStateValue != DebugPauseState::waitingForUserStartConfirmation); + std::cout << "Debug break: Press enter to start workload" << std::endl; + self->debugConfirmationFunction(); + debugPauseStateValue = DebugPauseState::hasUserStartConfirmation; + { + std::unique_lock lock{self->debugPauseStateLock}; + *self->debugPauseStateAddress = debugPauseStateValue; + } } - if (debugPauseStateValue == DebugPauseState::terminate) { - return nullptr; + if (DebugManager.flags.PauseOnGpuMode.get() != PauseOnGpuProperties::PauseMode::BeforeWorkload) { + do { + { + std::unique_lock lock{self->debugPauseStateLock}; + debugPauseStateValue = *self->debugPauseStateAddress; + } + if (debugPauseStateValue == DebugPauseState::terminate) { + return nullptr; + } + std::this_thread::yield(); + } while (debugPauseStateValue != DebugPauseState::waitingForUserEndConfirmation); + + std::cout << "Debug break: Workload ended, press enter to continue" << std::endl; + self->debugConfirmationFunction(); + + { + std::unique_lock lock{self->debugPauseStateLock}; + *self->debugPauseStateAddress = DebugPauseState::hasUserEndConfirmation; + } } - std::this_thread::yield(); - } while (debugPauseStateValue != DebugPauseState::waitingForUserStartConfirmation); - - std::cout << "Debug break: Press enter to start workload" << std::endl; - self->debugConfirmationFunction(); - - debugPauseStateValue = DebugPauseState::hasUserStartConfirmation; - { - std::unique_lock lock{self->debugPauseStateLock}; - *self->debugPauseStateAddress = debugPauseStateValue; - } - - do { - { - std::unique_lock lock{self->debugPauseStateLock}; - debugPauseStateValue = *self->debugPauseStateAddress; - } - if (debugPauseStateValue == DebugPauseState::terminate) { - return nullptr; - } - std::this_thread::yield(); - } while (debugPauseStateValue != DebugPauseState::waitingForUserEndConfirmation); - - std::cout << "Debug break: Workload ended, press enter to continue" << std::endl; - self->debugConfirmationFunction(); - - { - std::unique_lock lock{self->debugPauseStateLock}; - *self->debugPauseStateAddress = DebugPauseState::hasUserEndConfirmation; - } - + } while (DebugManager.flags.PauseOnEnqueue.get() == PauseOnGpuProperties::DebugFlagValues::OnEachEnqueue || DebugManager.flags.PauseOnBlitCopy.get() == PauseOnGpuProperties::DebugFlagValues::OnEachEnqueue); return nullptr; }