From 6e9257c62341affa80069aa8146b36b107ecad05 Mon Sep 17 00:00:00 2001 From: "Dunajski, Bartosz" Date: Mon, 24 Apr 2023 20:45:11 +0000 Subject: [PATCH] Debug flag to force early exit Signed-off-by: Dunajski, Bartosz --- .../debug_settings/debug_variables_base.inl | 2 + .../os_interface/linux/drm_command_stream.inl | 17 +++++ .../os_interface/linux/sys_calls_linux.cpp | 5 ++ shared/source/os_interface/sys_calls_common.h | 4 +- .../source/os_interface/windows/sys_calls.cpp | 7 +- .../linux/drm_command_stream_fixture.h | 1 + .../linux/sys_calls_linux_ult.cpp | 9 ++- .../os_interface/linux/sys_calls_linux_ult.h | 2 + .../common/os_interface/windows/sys_calls.cpp | 3 + shared/test/common/test_files/igdrcl.config | 2 + .../linux/drm_command_stream_tests_1.cpp | 73 +++++++++++++++++++ 11 files changed, 122 insertions(+), 3 deletions(-) diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 953baf98f4..83453c98a0 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -232,6 +232,8 @@ DECLARE_DEBUG_VARIABLE(int32_t, EnableMultipleRegularContextForBcs, -1, "-1: def DECLARE_DEBUG_VARIABLE(int32_t, AppendAubStreamContextFlags, -1, "-1: default, >0: Append flags passed during HardwareContext creation.") DECLARE_DEBUG_VARIABLE(int32_t, DisableScratchPages, -1, "-1: default, 0: do not disable scratch pages during VM creations, 1: disable scratch pages during VM creations") DECLARE_DEBUG_VARIABLE(int32_t, OptimizeIoqBarriersHandling, -1, "-1: default, 0: disable, 1: enable. If enabled, dont dispatch stalling commands for IOQ. Instead, inherit TimestampPackets from previous enqueue.") +DECLARE_DEBUG_VARIABLE(int32_t, ExitOnSubmissionNumber, -1, "Call exit(0) on X submission. >=0: submission count (start from 0)") +DECLARE_DEBUG_VARIABLE(int32_t, ExitOnSubmissionMode, 0, "Exit on X submission mode. 0: Any context type, 1: Compute context only, 2: Copy context only ") DECLARE_DEBUG_VARIABLE(int64_t, OverrideEventSynchronizeTimeout, -1, "-1: default - user provided timeout value, >0: timeout in nanoseconds") /*LOGGING FLAGS*/ diff --git a/shared/source/os_interface/linux/drm_command_stream.inl b/shared/source/os_interface/linux/drm_command_stream.inl index 7814aeb781..6ba7340668 100644 --- a/shared/source/os_interface/linux/drm_command_stream.inl +++ b/shared/source/os_interface/linux/drm_command_stream.inl @@ -25,6 +25,7 @@ #include "shared/source/os_interface/linux/drm_wrappers.h" #include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/source/os_interface/os_interface.h" +#include "shared/source/os_interface/sys_calls_common.h" namespace NEO { @@ -87,6 +88,22 @@ inline DrmCommandStreamReceiver::~DrmCommandStreamReceiver() { template SubmissionStatus DrmCommandStreamReceiver::flush(BatchBuffer &batchBuffer, ResidencyContainer &allocationsForResidency) { + if (DebugManager.flags.ExitOnSubmissionNumber.get() != -1) { + bool enabled = (this->taskCount >= static_cast(DebugManager.flags.ExitOnSubmissionNumber.get())); + + if (DebugManager.flags.ExitOnSubmissionMode.get() == 1 && !EngineHelpers::isComputeEngine(this->osContext->getEngineType())) { + enabled = false; + } + + if (DebugManager.flags.ExitOnSubmissionMode.get() == 2 && !EngineHelpers::isBcs(this->osContext->getEngineType())) { + enabled = false; + } + + if (enabled) { + SysCalls::exit(0); + } + } + this->printDeviceIndex(); DrmAllocation *alloc = static_cast(batchBuffer.commandBufferAllocation); DEBUG_BREAK_IF(!alloc); diff --git a/shared/source/os_interface/linux/sys_calls_linux.cpp b/shared/source/os_interface/linux/sys_calls_linux.cpp index f3f3596d44..28125903e9 100644 --- a/shared/source/os_interface/linux/sys_calls_linux.cpp +++ b/shared/source/os_interface/linux/sys_calls_linux.cpp @@ -7,6 +7,7 @@ #include "shared/source/os_interface/linux/sys_calls.h" +#include #include #include #include @@ -21,6 +22,10 @@ namespace NEO { namespace SysCalls { +void exit(int code) { + std::exit(code); +} + unsigned int getProcessId() { static unsigned int pid = getpid(); return pid; diff --git a/shared/source/os_interface/sys_calls_common.h b/shared/source/os_interface/sys_calls_common.h index ccbfde1863..ed0d8a7243 100644 --- a/shared/source/os_interface/sys_calls_common.h +++ b/shared/source/os_interface/sys_calls_common.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -15,6 +15,8 @@ unsigned int getProcessId(); unsigned long getNumThreads(); +void exit(int code); + } // namespace SysCalls } // namespace NEO diff --git a/shared/source/os_interface/windows/sys_calls.cpp b/shared/source/os_interface/windows/sys_calls.cpp index e4fd011215..b9fead7133 100644 --- a/shared/source/os_interface/windows/sys_calls.cpp +++ b/shared/source/os_interface/windows/sys_calls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,6 +7,8 @@ #include "shared/source/os_interface/windows/sys_calls.h" +#include + namespace NEO { unsigned int getPid() { @@ -25,6 +27,9 @@ bool isShutdownInProgress() { } namespace SysCalls { +void exit(int code) { + std::exit(code); +} unsigned int getProcessId() { return GetCurrentProcessId(); diff --git a/shared/test/common/os_interface/linux/drm_command_stream_fixture.h b/shared/test/common/os_interface/linux/drm_command_stream_fixture.h index 93560d9752..7178020de8 100644 --- a/shared/test/common/os_interface/linux/drm_command_stream_fixture.h +++ b/shared/test/common/os_interface/linux/drm_command_stream_fixture.h @@ -29,6 +29,7 @@ struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::dispatchMode; using DrmCommandStreamReceiver::completionFenceValuePointer; using DrmCommandStreamReceiver::flushInternal; + using DrmCommandStreamReceiver::CommandStreamReceiver::taskCount; }; class DrmCommandStreamTest : public ::testing::Test { diff --git a/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp b/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp index 41d646dde7..87b65cf4b5 100644 --- a/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp +++ b/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp @@ -31,7 +31,9 @@ uint32_t closeFuncCalled = 0u; int closeFuncArgPassed = 0; int closeFuncRetVal = 0; int dlOpenFlags = 0; -bool dlOpenCalled = 0; +int latestExitCode = 0; +bool exitCalled = false; +bool dlOpenCalled = false; bool getNumThreadsCalled = false; bool makeFakeDevicePath = false; bool allowFakeDevicePath = false; @@ -66,6 +68,11 @@ int (*sysCallsPipe)(int pipeFd[2]) = nullptr; int (*sysCallsFstat)(int fd, struct stat *buf) = nullptr; char *(*sysCallsRealpath)(const char *path, char *buf) = nullptr; +void exit(int code) { + exitCalled = true; + latestExitCode = code; +} + int close(int fileDescriptor) { closeFuncCalled++; closeFuncArgPassed = fileDescriptor; diff --git a/shared/test/common/os_interface/linux/sys_calls_linux_ult.h b/shared/test/common/os_interface/linux/sys_calls_linux_ult.h index c0cba83bb8..94a1be2bf9 100644 --- a/shared/test/common/os_interface/linux/sys_calls_linux_ult.h +++ b/shared/test/common/os_interface/linux/sys_calls_linux_ult.h @@ -33,6 +33,8 @@ extern int passedFileDescriptorFlagsToSet; extern int getFileDescriptorFlagsCalled; extern int setFileDescriptorFlagsCalled; extern uint32_t closeFuncCalled; +extern bool exitCalled; +extern int latestExitCode; extern std::vector mmapVector; extern std::vector mmapCapturedExtendedPointers; diff --git a/shared/test/common/os_interface/windows/sys_calls.cpp b/shared/test/common/os_interface/windows/sys_calls.cpp index 85fcfbbf1c..79c3242c32 100644 --- a/shared/test/common/os_interface/windows/sys_calls.cpp +++ b/shared/test/common/os_interface/windows/sys_calls.cpp @@ -33,6 +33,9 @@ const HKEY validHkey = reinterpret_cast(0); bool getNumThreadsCalled = false; bool mmapAllowExtendedPointers = false; +void exit(int code) { +} + HANDLE createEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName) { if (mockCreateEventClb) { return mockCreateEventClb(lpEventAttributes, bManualReset, bInitialState, lpName, mockCreateEventClbData); diff --git a/shared/test/common/test_files/igdrcl.config b/shared/test/common/test_files/igdrcl.config index f07876ea6e..2f1bdab20a 100644 --- a/shared/test/common/test_files/igdrcl.config +++ b/shared/test/common/test_files/igdrcl.config @@ -515,3 +515,5 @@ DetectIndirectAccessInKernel = -1 OptimizeIoqBarriersHandling = -1 AllocateSharedAllocationsInHeapExtended = 0 DirectSubmissionControllerMaxTimeout = -1 +ExitOnSubmissionNumber = -1 +ExitOnSubmissionMode = 0 \ No newline at end of file diff --git a/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp b/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp index 4d48fe7f44..f02bc1be24 100644 --- a/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp @@ -40,6 +40,13 @@ using namespace NEO; +namespace NEO { +namespace SysCalls { +extern bool exitCalled; +extern int latestExitCode; +} // namespace SysCalls +} // namespace NEO + HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenFlushStampWhenWaitCalledThenWaitForSpecifiedBoHandle) { FlushStamp handleToWait = 123; GemWait expectedWait = {}; @@ -51,6 +58,72 @@ HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenFlushStampWhenWaitCalledThenWaitFo EXPECT_EQ(1, mock->ioctlCount.gemWait); } +HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenDebugFlagSetWhenSubmittingThenCallExit) { + uint32_t expectedExitCounter = 13; + + DebugManager.flags.ExitOnSubmissionNumber.set(expectedExitCounter); + + csr->initializeTagAllocation(); + + auto &cs = csr->getCS(); + IndirectHeap ih(cs.getGraphicsAllocation()); + DispatchFlags dispatchFlags = DispatchFlagsHelper::createDefaultDispatchFlags(); + dispatchFlags.preemptionMode = PreemptionMode::Disabled; + + executionEnvironment.incRefInternal(); + std::unique_ptr device(MockDevice::create(&executionEnvironment, 0)); + device->setPreemptionMode(PreemptionMode::Disabled); + + bool bcsSupported = false; + for (auto &engine : csr->getGfxCoreHelper().getGpgpuEngineInstances(device->getRootDeviceEnvironment())) { + if (engine.first == aub_stream::EngineType::ENGINE_BCS) { + bcsSupported = true; + break; + } + } + + for (int32_t mode : {0, 1, 2}) { + DebugManager.flags.ExitOnSubmissionMode.set(mode); + + for (auto engineType : {aub_stream::ENGINE_BCS, EngineHelpers::remapEngineTypeToHwSpecific(aub_stream::ENGINE_RCS, device->getRootDeviceEnvironment())}) { + if (engineType == aub_stream::ENGINE_BCS && !bcsSupported) { + continue; + } + + osContext = std::make_unique(*mock, 0, 0, + EngineDescriptorHelper::getDefaultDescriptor({engineType, EngineUsage::Regular}, PreemptionMode::ThreadGroup)); + + osContext->ensureContextInitialized(); + + csr->setupContext(*osContext); + static_cast *>(csr)->taskCount = 0; + + for (uint32_t i = 0; i <= expectedExitCounter + 3; i++) { + SysCalls::exitCalled = false; + + csr->flushTask(cs, 0u, &ih, &ih, &ih, 0u, dispatchFlags, *device); + + bool enabled = (i >= expectedExitCounter); + + if (mode == 1 && !EngineHelpers::isComputeEngine(engineType)) { + enabled = false; + } + + if (mode == 2 && !EngineHelpers::isBcs(engineType)) { + enabled = false; + } + + if (enabled) { + EXPECT_TRUE(SysCalls::exitCalled); + EXPECT_EQ(0, SysCalls::latestExitCode); + } else { + EXPECT_FALSE(SysCalls::exitCalled); + } + } + } + } +} + HWTEST_TEMPLATED_F(DrmCommandStreamTest, WhenMakingResidentThenSucceeds) { DrmAllocation graphicsAllocation(0, AllocationType::UNKNOWN, nullptr, nullptr, 1024, static_cast(1u), MemoryPool::MemoryNull); csr->makeResident(graphicsAllocation);