From f63dd1f4f2648f8becdbc0fbdf455379b5810ee5 Mon Sep 17 00:00:00 2001 From: Mateusz Jablonski Date: Mon, 20 Nov 2023 17:47:53 +0000 Subject: [PATCH] fix: don't fail entire initialization when at least one device is compatible Related-To: NEO-6683 Signed-off-by: Mateusz Jablonski --- .../root_device_environment.h | 2 +- shared/source/os_interface/device_factory.cpp | 8 ++- .../mocks/mock_execution_environment.cpp | 19 +++++++ .../common/mocks/mock_execution_environment.h | 10 +++- .../os_interface/device_factory_tests.cpp | 53 +++++++++++++++++++ 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/shared/source/execution_environment/root_device_environment.h b/shared/source/execution_environment/root_device_environment.h index ca6f6580ebc74..f574c7e52e8cf 100644 --- a/shared/source/execution_environment/root_device_environment.h +++ b/shared/source/execution_environment/root_device_environment.h @@ -61,7 +61,7 @@ struct RootDeviceEnvironment : NonCopyableClass { bool isWddmOnLinux() const; MOCKABLE_VIRTUAL void initAubCenter(bool localMemoryEnabled, const std::string &aubFileName, CommandStreamReceiverType csrType); - bool initOsInterface(std::unique_ptr &&hwDeviceId, uint32_t rootDeviceIndex); + MOCKABLE_VIRTUAL bool initOsInterface(std::unique_ptr &&hwDeviceId, uint32_t rootDeviceIndex); void initOsTime(); void initGmm(); void initDebuggerL0(Device *neoDevice); diff --git a/shared/source/os_interface/device_factory.cpp b/shared/source/os_interface/device_factory.cpp index ae0aae7c705ce..d47a5b0509c87 100644 --- a/shared/source/os_interface/device_factory.cpp +++ b/shared/source/os_interface/device_factory.cpp @@ -170,12 +170,18 @@ bool DeviceFactory::prepareDeviceEnvironments(ExecutionEnvironment &executionEnv for (auto &hwDeviceId : hwDeviceIds) { if (initHwDeviceIdResources(executionEnvironment, std::move(hwDeviceId), rootDeviceIndex) == false) { - return false; + continue; } rootDeviceIndex++; } + executionEnvironment.rootDeviceEnvironments.resize(rootDeviceIndex); + + if (rootDeviceIndex == 0) { + return false; + } + executionEnvironment.setDeviceHierarchy(executionEnvironment.rootDeviceEnvironments[0]->getHelper()); executionEnvironment.sortNeoDevices(); executionEnvironment.parseAffinityMask(); diff --git a/shared/test/common/mocks/mock_execution_environment.cpp b/shared/test/common/mocks/mock_execution_environment.cpp index 2118fa06ee318..23d090ecc1d76 100644 --- a/shared/test/common/mocks/mock_execution_environment.cpp +++ b/shared/test/common/mocks/mock_execution_environment.cpp @@ -10,6 +10,8 @@ #include "shared/test/common/fixtures/mock_aub_center_fixture.h" #include "shared/test/common/helpers/default_hw_info.h" +#include "gtest/gtest.h" + namespace NEO { extern bool useMockGmm; @@ -24,6 +26,23 @@ void MockRootDeviceEnvironment::initAubCenter(bool localMemoryEnabled, const std } RootDeviceEnvironment::initAubCenter(localMemoryEnabled, aubFileName, csrType); } +bool MockRootDeviceEnvironment::initOsInterface(std::unique_ptr &&hwDeviceId, uint32_t rootDeviceIndex) { + initOsInterfaceCalled++; + if (!initOsInterfaceResults.empty()) { + auto retVal = initOsInterfaceResults[initOsInterfaceCalled - 1]; + if (retVal) { + RootDeviceEnvironment::initOsInterface(std::move(hwDeviceId), rootDeviceIndex); + } + return retVal; + } + return RootDeviceEnvironment::initOsInterface(std::move(hwDeviceId), rootDeviceIndex); +} + +MockRootDeviceEnvironment::~MockRootDeviceEnvironment() { + if (initOsInterfaceExpectedCallCount) { + EXPECT_EQ(*initOsInterfaceExpectedCallCount, initOsInterfaceCalled); + } +} MockExecutionEnvironment::MockExecutionEnvironment() : MockExecutionEnvironment(defaultHwInfo.get()) {} MockExecutionEnvironment::MockExecutionEnvironment(const HardwareInfo *hwInfo) : MockExecutionEnvironment(hwInfo, true, 1u) { diff --git a/shared/test/common/mocks/mock_execution_environment.h b/shared/test/common/mocks/mock_execution_environment.h index bfdf44273dad3..2a302a749fd6b 100644 --- a/shared/test/common/mocks/mock_execution_environment.h +++ b/shared/test/common/mocks/mock_execution_environment.h @@ -10,16 +10,24 @@ #include "shared/source/execution_environment/execution_environment.h" #include "shared/source/execution_environment/root_device_environment.h" +#include + namespace NEO { struct MockRootDeviceEnvironment : public RootDeviceEnvironment { + using BaseClass = RootDeviceEnvironment; using RootDeviceEnvironment::hwInfo; using RootDeviceEnvironment::isDummyAllocationInitialized; using RootDeviceEnvironment::isWddmOnLinuxEnable; using RootDeviceEnvironment::RootDeviceEnvironment; - ~MockRootDeviceEnvironment() override = default; + ~MockRootDeviceEnvironment() override; void initAubCenter(bool localMemoryEnabled, const std::string &aubFileName, CommandStreamReceiverType csrType) override; + bool initOsInterface(std::unique_ptr &&hwDeviceId, uint32_t rootDeviceIndex) override; + + std::vector initOsInterfaceResults; + uint32_t initOsInterfaceCalled = 0u; + std::optional initOsInterfaceExpectedCallCount; bool initAubCenterCalled = false; bool localMemoryEnabledReceived = false; std::string aubFileNameReceived = ""; diff --git a/shared/test/unit_test/os_interface/device_factory_tests.cpp b/shared/test/unit_test/os_interface/device_factory_tests.cpp index dbace265018ff..48db65eac1358 100644 --- a/shared/test/unit_test/os_interface/device_factory_tests.cpp +++ b/shared/test/unit_test/os_interface/device_factory_tests.cpp @@ -121,3 +121,56 @@ TEST_F(DeviceFactoryTests, givenDisabledRcsWhenPrepareDeviceEnvironmentsCalledTh EXPECT_NE(executionEnvironment.rootDeviceEnvironments[0]->getHardwareInfo()->featureTable.flags.ftrRcsNode, releaseHelper->isRcsExposureDisabled()); } } + +TEST_F(DeviceFactoryTests, givenMultipleDevicesWhenInitializeResourcesSucceedsForAtLeastOneDeviceThenSuccessIsReturned) { + DebugManagerStateRestore restorer; + DebugManager.flags.CreateMultipleRootDevices.set(3); + MockExecutionEnvironment executionEnvironment(defaultHwInfo.get(), true, 3u); + + EXPECT_EQ(3u, executionEnvironment.rootDeviceEnvironments.size()); + auto rootDeviceEnvironment0 = static_cast(executionEnvironment.rootDeviceEnvironments[0].get()); + auto rootDeviceEnvironment1 = static_cast(executionEnvironment.rootDeviceEnvironments[1].get()); + auto rootDeviceEnvironment2 = static_cast(executionEnvironment.rootDeviceEnvironments[2].get()); + + rootDeviceEnvironment0->initOsInterfaceResults.push_back(true); + rootDeviceEnvironment0->initOsInterfaceExpectedCallCount = 1u; + + // making rootDeviceEnvironment1 returning false on first call and true on second call + rootDeviceEnvironment1->initOsInterfaceResults.push_back(false); + rootDeviceEnvironment1->initOsInterfaceResults.push_back(true); + rootDeviceEnvironment1->initOsInterfaceExpectedCallCount = 2u; + + rootDeviceEnvironment2->initOsInterfaceExpectedCallCount = 0u; + + bool success = DeviceFactory::prepareDeviceEnvironments(executionEnvironment); + ASSERT_TRUE(success); + + EXPECT_EQ(2u, executionEnvironment.rootDeviceEnvironments.size()); + + EXPECT_EQ(1u, rootDeviceEnvironment0->initOsInterfaceCalled); + EXPECT_EQ(2u, rootDeviceEnvironment1->initOsInterfaceCalled); +} + +TEST_F(DeviceFactoryTests, givenMultipleDevicesWhenInitializeResourcesFailsForAllDevicesThenFailureIsReturned) { + DebugManagerStateRestore restorer; + DebugManager.flags.CreateMultipleRootDevices.set(3); + MockExecutionEnvironment executionEnvironment(defaultHwInfo.get(), true, 3u); + + EXPECT_EQ(3u, executionEnvironment.rootDeviceEnvironments.size()); + auto rootDeviceEnvironment0 = static_cast(executionEnvironment.rootDeviceEnvironments[0].get()); + auto rootDeviceEnvironment1 = static_cast(executionEnvironment.rootDeviceEnvironments[1].get()); + auto rootDeviceEnvironment2 = static_cast(executionEnvironment.rootDeviceEnvironments[2].get()); + + // making root device environment failing three times (once per device) + rootDeviceEnvironment0->initOsInterfaceResults.push_back(false); + rootDeviceEnvironment0->initOsInterfaceResults.push_back(false); + rootDeviceEnvironment0->initOsInterfaceResults.push_back(false); + rootDeviceEnvironment0->initOsInterfaceExpectedCallCount = 3u; + rootDeviceEnvironment1->initOsInterfaceExpectedCallCount = 0u; + rootDeviceEnvironment2->initOsInterfaceExpectedCallCount = 0u; + + bool success = DeviceFactory::prepareDeviceEnvironments(executionEnvironment); + EXPECT_FALSE(success); + + EXPECT_EQ(0u, executionEnvironment.rootDeviceEnvironments.size()); +}