mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-08 14:02:58 +08:00
fix: check exception reason for stopped threads
- before marking interrupt request check exception reason. If there is exception other than forced exception or forced external halt treat thread as stopped and generate distinct event for it. Related-To: NEO-7869 Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
e695059152
commit
e26ebfc51b
@@ -677,7 +677,7 @@ bool DebugSessionImp::readSystemRoutineIdent(EuThread *thread, uint64_t memoryHa
|
||||
return true;
|
||||
}
|
||||
|
||||
void DebugSessionImp::markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(EuThread::ThreadId threadId, uint64_t memoryHandle) {
|
||||
void DebugSessionImp::addThreadToNewlyStoppedFromRaisedAttention(EuThread::ThreadId threadId, uint64_t memoryHandle) {
|
||||
|
||||
SIP::sr_ident srMagic = {{0}};
|
||||
srMagic.count = 0;
|
||||
@@ -702,24 +702,7 @@ void DebugSessionImp::markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentio
|
||||
allThreads[threadId]->stopThread(memoryHandle);
|
||||
}
|
||||
|
||||
bool threadWasInterrupted = false;
|
||||
|
||||
for (auto &request : pendingInterrupts) {
|
||||
ze_device_thread_t apiThread = convertToApi(threadId);
|
||||
|
||||
auto isInterrupted = checkSingleThreadWithinDeviceThread(apiThread, request.first);
|
||||
|
||||
if (isInterrupted) {
|
||||
// mark pending interrupt as completed successfully only when new thread has been stopped
|
||||
if (!wasStopped) {
|
||||
request.second = true;
|
||||
}
|
||||
threadWasInterrupted = true;
|
||||
allThreads[threadId]->reportAsStopped();
|
||||
}
|
||||
}
|
||||
|
||||
if (!threadWasInterrupted && !wasStopped) {
|
||||
if (!wasStopped) {
|
||||
newlyStoppedThreads.push_back(threadId);
|
||||
}
|
||||
}
|
||||
@@ -737,8 +720,9 @@ void DebugSessionImp::generateEventsAndResumeStoppedThreads() {
|
||||
if (triggerEvents) {
|
||||
std::vector<EuThread::ThreadId> resumeThreads;
|
||||
std::vector<EuThread::ThreadId> stoppedThreadsToReport;
|
||||
std::vector<EuThread::ThreadId> interruptedThreads;
|
||||
|
||||
fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreadsToReport);
|
||||
fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreadsToReport, interruptedThreads);
|
||||
|
||||
resumeAccidentallyStoppedThreads(resumeThreads);
|
||||
generateEventsForPendingInterrupts();
|
||||
@@ -756,7 +740,7 @@ bool DebugSessionImp::isForceExceptionOrForceExternalHaltOnlyExceptionReason(uin
|
||||
return (((cr0[1] & cr0ExceptionBitmask) & (~cr0ForcedExcpetionBitmask)) == 0);
|
||||
}
|
||||
|
||||
void DebugSessionImp::fillResumeAndStoppedThreadsFromNewlyStopped(std::vector<EuThread::ThreadId> &resumeThreads, std::vector<EuThread::ThreadId> &stoppedThreadsToReport) {
|
||||
void DebugSessionImp::fillResumeAndStoppedThreadsFromNewlyStopped(std::vector<EuThread::ThreadId> &resumeThreads, std::vector<EuThread::ThreadId> &stoppedThreadsToReport, std::vector<EuThread::ThreadId> &interruptedThreads) {
|
||||
|
||||
if (newlyStoppedThreads.empty()) {
|
||||
return;
|
||||
@@ -770,8 +754,27 @@ void DebugSessionImp::fillResumeAndStoppedThreadsFromNewlyStopped(std::vector<Eu
|
||||
readRegistersImp(newlyStopped, ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU, 0, 1, reg.get());
|
||||
|
||||
if (isForceExceptionOrForceExternalHaltOnlyExceptionReason(reg.get())) {
|
||||
PRINT_DEBUGGER_THREAD_LOG("RESUME accidentally stopped thread = %s\n", allThreads[newlyStopped]->toString().c_str());
|
||||
resumeThreads.push_back(newlyStopped);
|
||||
bool threadWasInterrupted = false;
|
||||
|
||||
for (auto &request : pendingInterrupts) {
|
||||
ze_device_thread_t apiThread = convertToApi(newlyStopped);
|
||||
|
||||
auto isInterrupted = checkSingleThreadWithinDeviceThread(apiThread, request.first);
|
||||
|
||||
if (isInterrupted) {
|
||||
// mark pending interrupt as completed successfully
|
||||
request.second = true;
|
||||
threadWasInterrupted = true;
|
||||
allThreads[newlyStopped]->reportAsStopped();
|
||||
}
|
||||
}
|
||||
|
||||
if (threadWasInterrupted) {
|
||||
interruptedThreads.push_back(newlyStopped);
|
||||
} else {
|
||||
PRINT_DEBUGGER_THREAD_LOG("RESUME accidentally stopped thread = %s\n", allThreads[newlyStopped]->toString().c_str());
|
||||
resumeThreads.push_back(newlyStopped);
|
||||
}
|
||||
} else {
|
||||
PRINT_DEBUGGER_THREAD_LOG("Newly stopped thread = %s, exception bits = %#010" PRIx32 "\n", allThreads[newlyStopped]->toString().c_str(), reg[1]);
|
||||
stoppedThreadsToReport.push_back(newlyStopped);
|
||||
|
||||
@@ -95,8 +95,8 @@ struct DebugSessionImp : DebugSession {
|
||||
ze_result_t readSbaRegisters(EuThread::ThreadId thread, uint32_t start, uint32_t count, void *pRegisterValues);
|
||||
MOCKABLE_VIRTUAL bool isForceExceptionOrForceExternalHaltOnlyExceptionReason(uint32_t *cr0);
|
||||
void sendInterrupts();
|
||||
MOCKABLE_VIRTUAL void markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(EuThread::ThreadId threadId, uint64_t memoryHandle);
|
||||
MOCKABLE_VIRTUAL void fillResumeAndStoppedThreadsFromNewlyStopped(std::vector<EuThread::ThreadId> &resumeThreads, std::vector<EuThread::ThreadId> &stoppedThreadsToReport);
|
||||
MOCKABLE_VIRTUAL void addThreadToNewlyStoppedFromRaisedAttention(EuThread::ThreadId threadId, uint64_t memoryHandle);
|
||||
MOCKABLE_VIRTUAL void fillResumeAndStoppedThreadsFromNewlyStopped(std::vector<EuThread::ThreadId> &resumeThreads, std::vector<EuThread::ThreadId> &stoppedThreadsToReport, std::vector<EuThread::ThreadId> &interruptedThreads);
|
||||
MOCKABLE_VIRTUAL void generateEventsAndResumeStoppedThreads();
|
||||
MOCKABLE_VIRTUAL void resumeAccidentallyStoppedThreads(const std::vector<EuThread::ThreadId> &threadIds);
|
||||
MOCKABLE_VIRTUAL void generateEventsForStoppedThreads(const std::vector<EuThread::ThreadId> &threadIds);
|
||||
|
||||
@@ -333,12 +333,12 @@ void *DebugSessionLinux::asyncThreadFunction(void *arg) {
|
||||
|
||||
if (self->tileSessionsEnabled) {
|
||||
for (size_t tileIndex = 0; tileIndex < self->tileSessions.size(); tileIndex++) {
|
||||
static_cast<TileDebugSessionLinux *>(self->tileSessions[tileIndex].first)->sendInterrupts();
|
||||
static_cast<TileDebugSessionLinux *>(self->tileSessions[tileIndex].first)->generateEventsAndResumeStoppedThreads();
|
||||
static_cast<TileDebugSessionLinux *>(self->tileSessions[tileIndex].first)->sendInterrupts();
|
||||
}
|
||||
} else {
|
||||
self->sendInterrupts();
|
||||
self->generateEventsAndResumeStoppedThreads();
|
||||
self->sendInterrupts();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1296,9 +1296,9 @@ void DebugSessionLinux::handleAttentionEvent(prelim_drm_i915_debug_event_eu_atte
|
||||
PRINT_DEBUGGER_THREAD_LOG("ATTENTION event for thread: %s\n", EuThread::toString(threadId).c_str());
|
||||
|
||||
if (tileSessionsEnabled) {
|
||||
static_cast<TileDebugSessionLinux *>(tileSessions[tileIndex].first)->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(threadId, vmHandle);
|
||||
static_cast<TileDebugSessionLinux *>(tileSessions[tileIndex].first)->addThreadToNewlyStoppedFromRaisedAttention(threadId, vmHandle);
|
||||
} else {
|
||||
markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(threadId, vmHandle);
|
||||
addThreadToNewlyStoppedFromRaisedAttention(threadId, vmHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,8 +126,8 @@ void *DebugSessionWindows::asyncThreadFunction(void *arg) {
|
||||
|
||||
while (self->asyncThread.threadActive) {
|
||||
self->readAndHandleEvent(100);
|
||||
self->sendInterrupts();
|
||||
self->generateEventsAndResumeStoppedThreads();
|
||||
self->sendInterrupts();
|
||||
}
|
||||
|
||||
PRINT_DEBUGGER_INFO_LOG("Debugger async thread closing\n", "");
|
||||
@@ -264,7 +264,7 @@ ze_result_t DebugSessionWindows::handleEuAttentionBitsEvent(DBGUMD_READ_EVENT_EU
|
||||
|
||||
for (auto &threadId : threadsWithAttention) {
|
||||
PRINT_DEBUGGER_THREAD_LOG("ATTENTION event for thread: %s\n", EuThread::toString(threadId).c_str());
|
||||
markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(threadId, memoryHandle);
|
||||
addThreadToNewlyStoppedFromRaisedAttention(threadId, memoryHandle);
|
||||
}
|
||||
|
||||
checkTriggerEventsForAttention();
|
||||
|
||||
@@ -223,11 +223,36 @@ TEST(DebugSessionTest, givenPendingInteruptWhenHandlingThreadWithAttentionThenPe
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
sessionMock->sendInterrupts();
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_TRUE(sessionMock->allThreads[thread]->isStopped());
|
||||
|
||||
EXPECT_FALSE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
|
||||
sessionMock->triggerEvents = true;
|
||||
|
||||
std::vector<EuThread::ThreadId> resumeThreads;
|
||||
std::vector<EuThread::ThreadId> stoppedThreadsToReport;
|
||||
std::vector<EuThread::ThreadId> interruptedThreads;
|
||||
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreadsToReport, interruptedThreads);
|
||||
EXPECT_EQ(1u, interruptedThreads.size());
|
||||
EXPECT_TRUE(sessionMock->pendingInterrupts[0].second);
|
||||
|
||||
sessionMock->generateEventsForPendingInterrupts();
|
||||
|
||||
ASSERT_EQ(1u, sessionMock->apiEvents.size());
|
||||
|
||||
zet_debug_event_t debugEvent = {};
|
||||
sessionMock->readEvent(0, &debugEvent);
|
||||
|
||||
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_THREAD_STOPPED, debugEvent.type);
|
||||
EXPECT_EQ(apiThread.thread, debugEvent.info.thread.thread.thread);
|
||||
EXPECT_EQ(apiThread.eu, debugEvent.info.thread.thread.eu);
|
||||
EXPECT_EQ(apiThread.subslice, debugEvent.info.thread.thread.subslice);
|
||||
EXPECT_EQ(apiThread.slice, debugEvent.info.thread.thread.slice);
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
}
|
||||
|
||||
@@ -253,7 +278,7 @@ TEST(DebugSessionTest, givenPreviouslyStoppedThreadAndPendingInterruptWhenHandli
|
||||
sessionMock->onlyForceException = false;
|
||||
sessionMock->allThreads[thread]->stopThread(1u);
|
||||
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_TRUE(sessionMock->allThreads[thread]->isStopped());
|
||||
|
||||
@@ -269,6 +294,85 @@ TEST(DebugSessionTest, givenPreviouslyStoppedThreadAndPendingInterruptWhenHandli
|
||||
EXPECT_TRUE(DebugSession::areThreadsEqual(apiThread, sessionMock->apiEvents.front().info.thread.thread));
|
||||
}
|
||||
|
||||
TEST(DebugSessionTest, givenThreadsStoppedOnBreakpointAndInterruptedWhenHandlingThreadsStateThenThreadsWithBreakpointExceptionsHaveDistinctEventsTriggered) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
auto hwInfo = *NEO::defaultHwInfo.get();
|
||||
|
||||
NEO::MockDevice *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
|
||||
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
|
||||
|
||||
auto sessionMock = std::make_unique<MockDebugSession>(config, &deviceImp);
|
||||
|
||||
sessionMock->callBaseIsForceExceptionOrForceExternalHaltOnlyExceptionReason = true;
|
||||
sessionMock->stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(2);
|
||||
|
||||
{
|
||||
auto pStateSaveAreaHeader = reinterpret_cast<SIP::StateSaveAreaHeader *>(sessionMock->stateSaveAreaHeader.data());
|
||||
auto size = pStateSaveAreaHeader->versionHeader.size * 8 +
|
||||
pStateSaveAreaHeader->regHeader.state_area_offset +
|
||||
pStateSaveAreaHeader->regHeader.state_save_size * 16;
|
||||
sessionMock->stateSaveAreaHeader.resize(size);
|
||||
}
|
||||
|
||||
auto *regdesc = &(reinterpret_cast<SIP::StateSaveAreaHeader *>(sessionMock->stateSaveAreaHeader.data()))->regHeader.cr;
|
||||
uint32_t cr0[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
ze_device_thread_t interruptThread = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
|
||||
ze_device_thread_t bpThread = {0, 0, 0, 0};
|
||||
EuThread::ThreadId threadWithBp(0, 0, 0, 0, 0);
|
||||
EuThread::ThreadId threadWithFe(0, 0, 0, 0, 1);
|
||||
|
||||
auto result = sessionMock->interrupt(interruptThread);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
sessionMock->sendInterrupts();
|
||||
|
||||
cr0[1] = 1 << 15 | 1 << 31;
|
||||
sessionMock->registersAccessHelper(sessionMock->allThreads[threadWithBp].get(), regdesc, 0, 1, cr0, true);
|
||||
|
||||
cr0[1] = 1 << 26;
|
||||
sessionMock->registersAccessHelper(sessionMock->allThreads[threadWithFe].get(), regdesc, 0, 1, cr0, true);
|
||||
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(threadWithBp, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(threadWithFe, 1u);
|
||||
|
||||
EXPECT_TRUE(sessionMock->allThreads[threadWithBp]->isStopped());
|
||||
EXPECT_TRUE(sessionMock->allThreads[threadWithFe]->isStopped());
|
||||
|
||||
sessionMock->expectedAttentionEvents = 0;
|
||||
sessionMock->checkTriggerEventsForAttention();
|
||||
|
||||
sessionMock->generateEventsAndResumeStoppedThreads();
|
||||
|
||||
EXPECT_EQ(2u, sessionMock->apiEvents.size());
|
||||
|
||||
uint32_t stoppedEvents = 0;
|
||||
bool interruptEventFound = false;
|
||||
bool bpThreadFound = false;
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
|
||||
zet_debug_event_t outputEvent = {};
|
||||
auto result = sessionMock->readEvent(0, &outputEvent);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
if (result == ZE_RESULT_SUCCESS) {
|
||||
if (outputEvent.type == ZET_DEBUG_EVENT_TYPE_THREAD_STOPPED) {
|
||||
stoppedEvents++;
|
||||
if (DebugSession::areThreadsEqual(interruptThread, outputEvent.info.thread.thread)) {
|
||||
interruptEventFound = true;
|
||||
} else if (DebugSession::areThreadsEqual(bpThread, outputEvent.info.thread.thread)) {
|
||||
bpThreadFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(2u, stoppedEvents);
|
||||
EXPECT_TRUE(bpThreadFound);
|
||||
EXPECT_TRUE(interruptEventFound);
|
||||
}
|
||||
|
||||
TEST(DebugSessionTest, givenStoppedThreadWhenAddingNewlyStoppedThenThreadIsNotAdded) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
@@ -282,7 +386,7 @@ TEST(DebugSessionTest, givenStoppedThreadWhenAddingNewlyStoppedThenThreadIsNotAd
|
||||
EuThread::ThreadId thread(0, 0, 0, 0, 0);
|
||||
sessionMock->allThreads[thread]->stopThread(1u);
|
||||
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
}
|
||||
@@ -302,7 +406,7 @@ TEST(DebugSessionTest, givenNoPendingInterruptAndStoppedThreadWithForceException
|
||||
sessionMock->threadStopped = true;
|
||||
sessionMock->onlyForceException = true;
|
||||
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_FALSE(sessionMock->allThreads[thread]->isReportedAsStopped());
|
||||
@@ -324,7 +428,7 @@ TEST(DebugSessionTest, givenNoPendingInterruptAndStoppedThreadWhenGeneratingEven
|
||||
sessionMock->onlyForceException = false;
|
||||
sessionMock->triggerEvents = true;
|
||||
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_FALSE(sessionMock->allThreads[thread]->isReportedAsStopped());
|
||||
@@ -352,7 +456,7 @@ TEST(DebugSessionTest, givenNoStoppedThreadWhenAddingNewlyStoppedThenThreadIsNot
|
||||
sessionMock->threadStopped = 0;
|
||||
|
||||
EuThread::ThreadId thread(0, 0, 0, 0, 0);
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
}
|
||||
@@ -389,7 +493,7 @@ TEST(DebugSessionTest, givenTriggerEventsWhenGenerateEventsAndResumeCalledThenEv
|
||||
ze_device_thread_t apiThread2 = {0, 0, 1, 1};
|
||||
sessionMock->pendingInterrupts.push_back({apiThread, true});
|
||||
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(EuThread::ThreadId(0, apiThread2), 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(EuThread::ThreadId(0, apiThread2), 1u);
|
||||
|
||||
sessionMock->triggerEvents = true;
|
||||
sessionMock->interruptSent = true;
|
||||
@@ -481,7 +585,7 @@ TEST(DebugSessionTest, givenErrorFromReadSystemRoutineIdentWhenCheckingThreadSta
|
||||
sessionMock->readSystemRoutineIdentRetVal = false;
|
||||
EuThread::ThreadId thread(0, 0, 0, 0, 0);
|
||||
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttention(thread, 1u);
|
||||
|
||||
EXPECT_FALSE(sessionMock->allThreads[thread]->isStopped());
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
@@ -552,11 +656,12 @@ TEST(DebugSessionTest, givenStoppedThreadsWhenFillingResumeAndStoppedThreadsFrom
|
||||
{
|
||||
std::vector<EuThread::ThreadId> resumeThreads;
|
||||
std::vector<EuThread::ThreadId> stoppedThreads;
|
||||
std::vector<EuThread::ThreadId> interruptedThreads;
|
||||
|
||||
sessionMock->allThreads[thread]->stopThread(1u);
|
||||
sessionMock->allThreads[thread2]->stopThread(1u);
|
||||
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreads);
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreads, interruptedThreads);
|
||||
EXPECT_EQ(2u, resumeThreads.size());
|
||||
EXPECT_EQ(0u, stoppedThreads.size());
|
||||
}
|
||||
@@ -569,11 +674,12 @@ TEST(DebugSessionTest, givenStoppedThreadsWhenFillingResumeAndStoppedThreadsFrom
|
||||
{
|
||||
std::vector<EuThread::ThreadId> resumeThreads;
|
||||
std::vector<EuThread::ThreadId> stoppedThreads;
|
||||
std::vector<EuThread::ThreadId> interruptedThreads;
|
||||
|
||||
sessionMock->allThreads[thread]->stopThread(1u);
|
||||
sessionMock->allThreads[thread2]->stopThread(1u);
|
||||
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreads);
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreads, interruptedThreads);
|
||||
EXPECT_EQ(0u, resumeThreads.size());
|
||||
EXPECT_EQ(2u, stoppedThreads.size());
|
||||
}
|
||||
@@ -590,8 +696,9 @@ TEST(DebugSessionTest, givenNoThreadsStoppedWhenCallingfillResumeAndStoppedThrea
|
||||
auto sessionMock = std::make_unique<MockDebugSession>(config, &deviceImp);
|
||||
std::vector<EuThread::ThreadId> resumeThreads;
|
||||
std::vector<EuThread::ThreadId> stoppedThreads;
|
||||
std::vector<EuThread::ThreadId> interruptedThreads;
|
||||
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreads);
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreads, interruptedThreads);
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->readStateSaveAreaHeaderCalled);
|
||||
}
|
||||
|
||||
@@ -254,6 +254,8 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
|
||||
using L0::DebugSessionImp::detachTile;
|
||||
using L0::DebugSessionImp::enqueueApiEvent;
|
||||
using L0::DebugSessionImp::expectedAttentionEvents;
|
||||
using L0::DebugSessionImp::fillResumeAndStoppedThreadsFromNewlyStopped;
|
||||
using L0::DebugSessionImp::generateEventsForPendingInterrupts;
|
||||
using L0::DebugSessionImp::interruptSent;
|
||||
using L0::DebugSessionImp::isValidGpuAddress;
|
||||
using L0::DebugSessionImp::newAttentionRaised;
|
||||
@@ -456,9 +458,9 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
|
||||
return DebugSessionLinux::checkStoppedThreadsAndGenerateEvents(threads, memoryHandle, deviceIndex);
|
||||
}
|
||||
|
||||
void markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(EuThread::ThreadId threadId, uint64_t memoryHandle) override {
|
||||
markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentionCallCount++;
|
||||
return DebugSessionImp::markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention(threadId, memoryHandle);
|
||||
void addThreadToNewlyStoppedFromRaisedAttention(EuThread::ThreadId threadId, uint64_t memoryHandle) override {
|
||||
addThreadToNewlyStoppedFromRaisedAttentionCallCount++;
|
||||
return DebugSessionImp::addThreadToNewlyStoppedFromRaisedAttention(threadId, memoryHandle);
|
||||
}
|
||||
|
||||
TileDebugSessionLinux *createTileSession(const zet_debug_config_t &config, L0::Device *device, L0::DebugSessionImp *rootDebugSession) override;
|
||||
@@ -480,7 +482,7 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
|
||||
uint32_t interruptedDevice = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t processPendingVmBindEventsCalled = 0;
|
||||
uint32_t checkStoppedThreadsAndGenerateEventsCallCount = 0;
|
||||
uint32_t markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentionCallCount = 0;
|
||||
uint32_t addThreadToNewlyStoppedFromRaisedAttentionCallCount = 0;
|
||||
|
||||
std::vector<uint32_t> resumedDevices;
|
||||
std::vector<std::vector<EuThread::ThreadId>> resumedThreads;
|
||||
|
||||
@@ -5969,9 +5969,41 @@ TEST_F(DebugApiLinuxAttentionTest, GivenInterruptedThreadsWhenOnlySomeThreadsRai
|
||||
|
||||
sessionMock->handleEvent(reinterpret_cast<prelim_drm_i915_debug_event *>(data));
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_FALSE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_FALSE(sessionMock->pendingInterrupts[1].second);
|
||||
|
||||
std::vector<EuThread::ThreadId> resumeThreads;
|
||||
std::vector<EuThread::ThreadId> stoppedThreadsToReport;
|
||||
std::vector<EuThread::ThreadId> interruptedThreads;
|
||||
|
||||
sessionMock->fillResumeAndStoppedThreadsFromNewlyStopped(resumeThreads, stoppedThreadsToReport, interruptedThreads);
|
||||
EXPECT_EQ(1u, interruptedThreads.size());
|
||||
EXPECT_TRUE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_FALSE(sessionMock->pendingInterrupts[1].second);
|
||||
|
||||
sessionMock->generateEventsForPendingInterrupts();
|
||||
// 2 pending interrupts
|
||||
EXPECT_EQ(2u, sessionMock->apiEvents.size());
|
||||
|
||||
uint32_t stoppedEvents = 0;
|
||||
uint32_t notAvailableEvents = 0;
|
||||
|
||||
for (uint32_t i = 0; i < 2u; i++) {
|
||||
zet_debug_event_t outputEvent = {};
|
||||
auto result = sessionMock->readEvent(0, &outputEvent);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
if (result == ZE_RESULT_SUCCESS) {
|
||||
if (outputEvent.type == ZET_DEBUG_EVENT_TYPE_THREAD_STOPPED) {
|
||||
stoppedEvents++;
|
||||
} else if (outputEvent.type == ZET_DEBUG_EVENT_TYPE_THREAD_UNAVAILABLE) {
|
||||
notAvailableEvents++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(1u, stoppedEvents);
|
||||
EXPECT_EQ(1u, notAvailableEvents);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxAttentionTest, GivenSentInterruptWhenHandlingAttEventThenAttBitsAreSynchronouslyScannedAgainAndAllNewThreadsChecked) {
|
||||
@@ -6031,10 +6063,9 @@ TEST_F(DebugApiLinuxAttentionTest, GivenSentInterruptWhenHandlingAttEventThenAtt
|
||||
|
||||
sessionMock->handleEvent(reinterpret_cast<prelim_drm_i915_debug_event *>(data));
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_TRUE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_EQ(2u, sessionMock->newlyStoppedThreads.size());
|
||||
auto expectedThreadsToCheck = (hwInfo.capabilityTable.fusedEuEnabled && hwInfo.gtSystemInfo.MaxEuPerSubSlice != 8) ? 4u : 2u;
|
||||
EXPECT_EQ(expectedThreadsToCheck, sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentionCallCount);
|
||||
EXPECT_EQ(expectedThreadsToCheck, sessionMock->addThreadToNewlyStoppedFromRaisedAttentionCallCount);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxAttentionTest, GivenSentInterruptWhenSynchronouslyScannedAttBitsAreAllZeroOrErrorWhileHandlingAttEventThenThreadsFromEventAreChecked) {
|
||||
@@ -6094,10 +6125,9 @@ TEST_F(DebugApiLinuxAttentionTest, GivenSentInterruptWhenSynchronouslyScannedAtt
|
||||
|
||||
sessionMock->handleEvent(reinterpret_cast<prelim_drm_i915_debug_event *>(data));
|
||||
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_TRUE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_EQ(2u, sessionMock->newlyStoppedThreads.size());
|
||||
auto expectedThreadsToCheck = hwInfo.capabilityTable.fusedEuEnabled ? 4u : 2u;
|
||||
EXPECT_EQ(expectedThreadsToCheck, sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentionCallCount);
|
||||
EXPECT_EQ(expectedThreadsToCheck, sessionMock->addThreadToNewlyStoppedFromRaisedAttentionCallCount);
|
||||
|
||||
sessionMock->stoppedThreads[threads[0].packed] = 3;
|
||||
sessionMock->stoppedThreads[threads[1].packed] = 3;
|
||||
@@ -6106,14 +6136,13 @@ TEST_F(DebugApiLinuxAttentionTest, GivenSentInterruptWhenSynchronouslyScannedAtt
|
||||
|
||||
sessionMock->newlyStoppedThreads.clear();
|
||||
sessionMock->pendingInterrupts[0].second = false;
|
||||
sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentionCallCount = 0;
|
||||
sessionMock->addThreadToNewlyStoppedFromRaisedAttentionCallCount = 0;
|
||||
handler->ioctlRetVal = -1;
|
||||
|
||||
sessionMock->handleEvent(reinterpret_cast<prelim_drm_i915_debug_event *>(data));
|
||||
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_TRUE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_EQ(expectedThreadsToCheck, sessionMock->markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttentionCallCount);
|
||||
EXPECT_EQ(2u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_EQ(expectedThreadsToCheck, sessionMock->addThreadToNewlyStoppedFromRaisedAttentionCallCount);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxAttentionTest, GivenInterruptedThreadsWhenAttentionEventReceivedThenEventsTriggeredAfterExpectedAttentionEventCount) {
|
||||
@@ -6681,14 +6710,14 @@ TEST_F(DebugApiLinuxAsyncThreadTest, GivenInterruptedThreadsWhenNoAttentionEvent
|
||||
auto handler = new MockIoctlHandler;
|
||||
session->ioctlHandler.reset(handler);
|
||||
session->returnTimeDiff = DebugSessionLinux::interruptTimeout * 10;
|
||||
|
||||
session->startAsyncThread();
|
||||
session->synchronousInternalEventRead = true;
|
||||
|
||||
ze_device_thread_t thread = {0, 0, 0, UINT32_MAX};
|
||||
auto result = session->interrupt(thread);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
session->startAsyncThread();
|
||||
|
||||
while (session->getInternalEventCounter == 0)
|
||||
while (session->getInternalEventCounter < 2)
|
||||
;
|
||||
|
||||
session->closeAsyncThread();
|
||||
|
||||
@@ -1015,9 +1015,10 @@ TEST_F(TileAttachAsyncThreadTest, GivenInterruptedThreadsWhenNoAttentionEventIsR
|
||||
auto result = tileSessions[0]->interrupt(thread);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
rootSession->synchronousInternalEventRead = true;
|
||||
rootSession->startAsyncThread();
|
||||
|
||||
while (rootSession->getInternalEventCounter == 0)
|
||||
while (rootSession->getInternalEventCounter < 2)
|
||||
;
|
||||
|
||||
rootSession->closeAsyncThread();
|
||||
|
||||
@@ -138,6 +138,7 @@ struct MockDebugSession : public L0::DebugSessionImp {
|
||||
using L0::DebugSession::allThreads;
|
||||
using L0::DebugSession::debugArea;
|
||||
|
||||
using L0::DebugSessionImp::addThreadToNewlyStoppedFromRaisedAttention;
|
||||
using L0::DebugSessionImp::apiEvents;
|
||||
using L0::DebugSessionImp::applyResumeWa;
|
||||
using L0::DebugSessionImp::calculateThreadSlotOffset;
|
||||
@@ -148,7 +149,6 @@ struct MockDebugSession : public L0::DebugSessionImp {
|
||||
using L0::DebugSessionImp::generateEventsForStoppedThreads;
|
||||
using L0::DebugSessionImp::getRegisterSize;
|
||||
using L0::DebugSessionImp::getStateSaveAreaHeader;
|
||||
using L0::DebugSessionImp::markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention;
|
||||
using L0::DebugSessionImp::newAttentionRaised;
|
||||
using L0::DebugSessionImp::readSbaRegisters;
|
||||
using L0::DebugSessionImp::registersAccessHelper;
|
||||
@@ -310,6 +310,9 @@ struct MockDebugSession : public L0::DebugSessionImp {
|
||||
}
|
||||
|
||||
bool isForceExceptionOrForceExternalHaltOnlyExceptionReason(uint32_t *cr0) override {
|
||||
if (callBaseIsForceExceptionOrForceExternalHaltOnlyExceptionReason) {
|
||||
return isForceExceptionOrForceExternalHaltOnlyExceptionReasonBase(cr0);
|
||||
}
|
||||
return onlyForceException;
|
||||
}
|
||||
|
||||
@@ -437,6 +440,7 @@ struct MockDebugSession : public L0::DebugSessionImp {
|
||||
ze_result_t interruptImpResult = ZE_RESULT_SUCCESS;
|
||||
ze_result_t resumeImpResult = ZE_RESULT_SUCCESS;
|
||||
bool onlyForceException = true;
|
||||
bool callBaseIsForceExceptionOrForceExternalHaltOnlyExceptionReason = false;
|
||||
bool threadStopped = true;
|
||||
int areRequestedThreadsStoppedReturnValue = -1;
|
||||
bool readSystemRoutineIdentRetVal = true;
|
||||
|
||||
@@ -263,7 +263,7 @@ TEST_F(DebugApiWindowsAttentionTest, GivenEuAttentionEventEmptyBitmaskWhenHandli
|
||||
EXPECT_FALSE(sessionMock->triggerEvents);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsAttentionTest, GivenInterruptedThreadsWhenOnlySomeThreadsRaisesAttentionThenPendingInterruptsAreMarked) {
|
||||
TEST_F(DebugApiWindowsAttentionTest, GivenInterruptedThreadsWithOnlySomeThreadsRaisingAttentionWhenHandlingEventThenInterruptedThreadsAreAddedToNewlyStopped) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
|
||||
@@ -295,8 +295,8 @@ TEST_F(DebugApiWindowsAttentionTest, GivenInterruptedThreadsWhenOnlySomeThreadsR
|
||||
auto result = sessionMock->readAndHandleEvent(100);
|
||||
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_TRUE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_EQ(1u, sessionMock->newlyStoppedThreads.size());
|
||||
EXPECT_FALSE(sessionMock->pendingInterrupts[0].second);
|
||||
EXPECT_FALSE(sessionMock->pendingInterrupts[1].second);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user