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 <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski 2021-02-06 14:38:55 +00:00 committed by Compute-Runtime-Automation
parent 7b7ad9a5cb
commit a6d898a026
2 changed files with 217 additions and 40 deletions

View File

@ -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<FamilyType>(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<FamilyType>(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<FamilyType>(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<FamilyType>(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);

View File

@ -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<Experimenta
void *CommandStreamReceiver::asyncDebugBreakConfirmation(void *arg) {
auto self = reinterpret_cast<CommandStreamReceiver *>(arg);
auto debugPauseStateValue = DebugPauseState::waitingForUserStartConfirmation;
do {
{
std::unique_lock<SpinLock> lock{self->debugPauseStateLock};
debugPauseStateValue = *self->debugPauseStateAddress;
auto debugPauseStateValue = DebugPauseState::waitingForUserStartConfirmation;
if (DebugManager.flags.PauseOnGpuMode.get() != PauseOnGpuProperties::PauseMode::AfterWorkload) {
do {
{
std::unique_lock<SpinLock> 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<SpinLock> lock{self->debugPauseStateLock};
*self->debugPauseStateAddress = debugPauseStateValue;
}
}
if (debugPauseStateValue == DebugPauseState::terminate) {
return nullptr;
if (DebugManager.flags.PauseOnGpuMode.get() != PauseOnGpuProperties::PauseMode::BeforeWorkload) {
do {
{
std::unique_lock<SpinLock> 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<SpinLock> 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<SpinLock> lock{self->debugPauseStateLock};
*self->debugPauseStateAddress = debugPauseStateValue;
}
do {
{
std::unique_lock<SpinLock> 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<SpinLock> lock{self->debugPauseStateLock};
*self->debugPauseStateAddress = DebugPauseState::hasUserEndConfirmation;
}
} while (DebugManager.flags.PauseOnEnqueue.get() == PauseOnGpuProperties::DebugFlagValues::OnEachEnqueue || DebugManager.flags.PauseOnBlitCopy.get() == PauseOnGpuProperties::DebugFlagValues::OnEachEnqueue);
return nullptr;
}