Revert "Retry in loop when exec or bind fails with ENXIO"

This reverts commit ec13b185a3.

Signed-off-by: Compute-Runtime-Validation <compute-runtime-validation@intel.com>
This commit is contained in:
Compute-Runtime-Validation
2022-10-01 11:39:49 +02:00
committed by Compute-Runtime-Automation
parent 8240f65434
commit 95434f446f
4 changed files with 36 additions and 233 deletions

View File

@@ -147,26 +147,24 @@ int BufferObject::exec(uint32_t used, size_t startOffset, unsigned int flags, bo
int ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
if (ret != 0) {
do {
int err = this->drm->getErrno();
if (err == EOPNOTSUPP) {
PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(I915_GEM_EXECBUFFER2) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
return err;
}
int err = this->drm->getErrno();
if (err == EOPNOTSUPP) {
PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(I915_GEM_EXECBUFFER2) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
return err;
}
evictUnusedAllocations(false, true);
ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
evictUnusedAllocations(false, true);
ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
}
if (ret != 0) {
const auto status = evictUnusedAllocations(true, true);
if (status == MemoryOperationsStatus::GPU_HANG_DETECTED_DURING_OPERATION) {
PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "Error! GPU hang detected in BufferObject::exec(). Returning %d\n", gpuHangDetected);
return gpuHangDetected;
}
if (ret != 0) {
const auto status = evictUnusedAllocations(true, true);
if (status == MemoryOperationsStatus::GPU_HANG_DETECTED_DURING_OPERATION) {
PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "Error! GPU hang detected in BufferObject::exec(). Returning %d\n", gpuHangDetected);
return gpuHangDetected;
}
ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
}
} while (ret != 0 && this->drm->getErrno() == ENXIO);
ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
}
if (ret == 0) {

View File

@@ -1324,13 +1324,13 @@ uint64_t Drm::getPatIndex(Gmm *gmm, AllocationType allocationType, CacheRegion c
return patIndex;
}
int Drm::changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind) {
auto vmId = this->getVirtualMemoryAddressSpace(vmHandleId);
auto ioctlHelper = this->getIoctlHelper();
int changeBufferObjectBinding(Drm *drm, OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind) {
auto vmId = drm->getVirtualMemoryAddressSpace(vmHandleId);
auto ioctlHelper = drm->getIoctlHelper();
uint64_t flags = 0u;
if (this->isPerContextVMRequired()) {
if (drm->isPerContextVMRequired()) {
auto osContextLinux = static_cast<const OsContextLinux *>(osContext);
UNRECOVERABLE_IF(osContextLinux->getDrmVmIds().size() <= vmHandleId);
vmId = osContextLinux->getDrmVmIds()[vmHandleId];
@@ -1345,7 +1345,7 @@ int Drm::changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, Bu
bool bindCapture = bo->isMarkedForCapture();
bool bindImmediate = bo->isImmediateBindingRequired();
bool bindMakeResident = false;
if (this->useVMBindImmediate()) {
if (drm->useVMBindImmediate()) {
bindMakeResident = bo->isExplicitResidencyRequired();
bindImmediate = true;
}
@@ -1377,7 +1377,7 @@ int Drm::changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, Bu
VmBindExtSetPatT vmBindExtSetPat{};
if (this->isVmBindPatIndexProgrammingSupported()) {
if (drm->isVmBindPatIndexProgrammingSupported()) {
UNRECOVERABLE_IF(bo->peekPatIndex() == CommonConstants::unsupportedPatIndex);
ioctlHelper->fillVmBindExtSetPat(vmBindExtSetPat, bo->peekPatIndex(), castToUint64(extensions.get()));
vmBind.extensions = castToUint64(vmBindExtSetPat);
@@ -1390,13 +1390,13 @@ int Drm::changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, Bu
VmBindExtUserFenceT vmBindExtUserFence{};
if (this->useVMBindImmediate()) {
lock = this->lockBindFenceMutex();
if (drm->useVMBindImmediate()) {
lock = drm->lockBindFenceMutex();
if (!this->hasPageFaultSupport() || bo->isExplicitResidencyRequired()) {
if (!drm->hasPageFaultSupport() || bo->isExplicitResidencyRequired()) {
auto nextExtension = vmBind.extensions;
auto address = castToUint64(this->getFenceAddr(vmHandleId));
auto value = this->getNextFenceVal(vmHandleId);
auto address = castToUint64(drm->getFenceAddr(vmHandleId));
auto value = drm->getNextFenceVal(vmHandleId);
ioctlHelper->fillVmBindExtUserFence(vmBindExtUserFence, address, value, nextExtension);
vmBind.extensions = castToUint64(vmBindExtUserFence);
@@ -1409,7 +1409,7 @@ int Drm::changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, Bu
break;
}
this->setNewResourceBoundToVM(vmHandleId);
drm->setNewResourceBoundToVM(vmHandleId);
} else {
vmBind.handle = 0u;
ret = ioctlHelper->vmUnbind(vmBind);
@@ -1424,18 +1424,16 @@ int Drm::changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, Bu
}
int Drm::bindBufferObject(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo) {
auto ret = changeBufferObjectBinding(osContext, vmHandleId, bo, true);
auto ret = changeBufferObjectBinding(this, osContext, vmHandleId, bo, true);
if (ret != 0) {
do {
static_cast<DrmMemoryOperationsHandlerBind *>(this->rootDeviceEnvironment.memoryOperationsInterface.get())->evictUnusedAllocations(false, false);
ret = changeBufferObjectBinding(osContext, vmHandleId, bo, true);
} while (ret != 0 && getErrno() == ENXIO);
static_cast<DrmMemoryOperationsHandlerBind *>(this->rootDeviceEnvironment.memoryOperationsInterface.get())->evictUnusedAllocations(false, false);
ret = changeBufferObjectBinding(this, osContext, vmHandleId, bo, true);
}
return ret;
}
int Drm::unbindBufferObject(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo) {
return changeBufferObjectBinding(osContext, vmHandleId, bo, false);
return changeBufferObjectBinding(this, osContext, vmHandleId, bo, false);
}
int Drm::createDrmVirtualMemory(uint32_t &drmVmId) {

View File

@@ -129,7 +129,6 @@ class Drm : public DriverModel {
uint32_t getVirtualMemoryAddressSpace(uint32_t vmId) const;
MOCKABLE_VIRTUAL int bindBufferObject(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo);
MOCKABLE_VIRTUAL int unbindBufferObject(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo);
MOCKABLE_VIRTUAL int changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind);
int setupHardwareInfo(const DeviceDescriptor *, bool);
void setupSystemInfo(HardwareInfo *hwInfo, SystemInfo *sysInfo);
void setupCacheInfo(const HardwareInfo &hwInfo);

View File

@@ -55,14 +55,14 @@ TEST_F(DrmBufferObjectTest, GivenDetectedGpuHangDuringEvictUnusedAllocationsWhen
}
TEST_F(DrmBufferObjectTest, WhenSettingTilingThenCallSucceeds) {
mock->ioctl_expected.total = 1; // set_tiling
mock->ioctl_expected.total = 1; //set_tiling
auto tilingY = mock->getIoctlHelper()->getDrmParamValue(DrmParam::TilingY);
auto ret = bo->setTiling(tilingY, 0);
EXPECT_TRUE(ret);
}
TEST_F(DrmBufferObjectTest, WhenSettingSameTilingThenCallSucceeds) {
mock->ioctl_expected.total = 0; // set_tiling
mock->ioctl_expected.total = 0; //set_tiling
auto tilingY = mock->getIoctlHelper()->getDrmParamValue(DrmParam::TilingY);
bo->tilingMode = tilingY;
auto ret = bo->setTiling(tilingY, 0);
@@ -70,7 +70,7 @@ TEST_F(DrmBufferObjectTest, WhenSettingSameTilingThenCallSucceeds) {
}
TEST_F(DrmBufferObjectTest, GivenInvalidTilingWhenSettingTilingThenCallFails) {
mock->ioctl_expected.total = 1; // set_tiling
mock->ioctl_expected.total = 1; //set_tiling
auto tilingY = mock->getIoctlHelper()->getDrmParamValue(DrmParam::TilingY);
mock->ioctl_res = -1;
auto ret = bo->setTiling(tilingY, 0);
@@ -91,7 +91,7 @@ TEST_F(DrmBufferObjectTest, givenAddressThatWhenSizeIsAddedCrosses32BitBoundaryW
bo->setAddress(((uint64_t)1u << 32) - 0x1000u);
bo->setSize(0x1000);
bo->fillExecObject(execObject, osContext.get(), 0, 1);
// base address + size > size of 32bit address space
//base address + size > size of 32bit address space
EXPECT_TRUE(execObject.has48BAddressSupportFlag());
}
@@ -102,7 +102,7 @@ TEST_F(DrmBufferObjectTest, givenAddressThatWhenSizeIsAddedWithin32BitBoundaryWh
bo->setAddress(((uint64_t)1u << 32) - 0x1000u);
bo->setSize(0xFFF);
bo->fillExecObject(execObject, osContext.get(), 0, 1);
// base address + size < size of 32bit address space
//base address + size < size of 32bit address space
EXPECT_TRUE(execObject.has48BAddressSupportFlag());
}
@@ -465,136 +465,6 @@ TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindSucceedsThenPr
EXPECT_STREQ(unbindOutput.c_str(), "unbind BO-0 from VM 0, drmVmId = 1, range: 0 - 0, size: 0, result: 0\n");
}
TEST(DrmBufferObject, givenBufferObjectWhenFirstChangeBufferObjectBindingReturnSuccessThenItsNotCalledAnyMore) {
struct DrmMockToSucceedBindBufferObject : public DrmMock {
DrmMockToSucceedBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment)
: DrmMock(rootDeviceEnvironment) {}
int changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind) override {
changeBufferObjectBindingCalled++;
return changeBufferObjectBindingCalled >= 1 ? 0 : -1;
}
uint32_t changeBufferObjectBindingCalled = 0;
};
auto executionEnvironment = std::make_unique<ExecutionEnvironment>();
executionEnvironment->setDebuggingEnabled();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->calculateMaxOsContextCount();
executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
auto drm = std::make_unique<DrmMockToSucceedBindBufferObject>(*executionEnvironment->rootDeviceEnvironments[0]);
auto drmPtr = drm.get();
executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm.get()));
executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm.release(), 0u);
std::unique_ptr<Device> device(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(), executionEnvironment.release(), 0));
auto osContextCount = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount();
MockBufferObject bo(drmPtr, 3, 0, 0, osContextCount);
auto contextId = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount() / 2;
auto osContext = device->getExecutionEnvironment()->memoryManager->getRegisteredEngines()[contextId].osContext;
auto ret = drmPtr->bindBufferObject(osContext, 0, &bo);
EXPECT_EQ(ret, 0);
EXPECT_EQ(drmPtr->changeBufferObjectBindingCalled, 1u);
}
TEST(DrmBufferObject, givenBufferObjectWhenSecondChangeBufferObjectBindingReturnSuccessThenItsNotCalledAnyMore) {
struct DrmMockToSucceedBindBufferObject : public DrmMock {
DrmMockToSucceedBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment)
: DrmMock(rootDeviceEnvironment) {}
int changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind) override {
changeBufferObjectBindingCalled++;
return changeBufferObjectBindingCalled >= 2 ? 0 : -1;
}
uint32_t changeBufferObjectBindingCalled = 0;
};
auto executionEnvironment = std::make_unique<ExecutionEnvironment>();
executionEnvironment->setDebuggingEnabled();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->calculateMaxOsContextCount();
executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
auto drm = std::make_unique<DrmMockToSucceedBindBufferObject>(*executionEnvironment->rootDeviceEnvironments[0]);
auto drmPtr = drm.get();
executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm.get()));
executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm.release(), 0u);
std::unique_ptr<Device> device(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(), executionEnvironment.release(), 0));
auto osContextCount = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount();
MockBufferObject bo(drmPtr, 3, 0, 0, osContextCount);
auto contextId = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount() / 2;
auto osContext = device->getExecutionEnvironment()->memoryManager->getRegisteredEngines()[contextId].osContext;
auto ret = drmPtr->bindBufferObject(osContext, 0, &bo);
EXPECT_EQ(ret, 0);
EXPECT_EQ(drmPtr->changeBufferObjectBindingCalled, 2u);
}
TEST(DrmBufferObject, givenBufferObjectWhenSecondChangeBufferObjectBindingReturnFailAndErrnoIsNotENXIOThenItsNotCalledAnyMore) {
struct DrmMockToSucceedBindBufferObject : public DrmMock {
DrmMockToSucceedBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment)
: DrmMock(rootDeviceEnvironment) {}
int changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind) override {
changeBufferObjectBindingCalled++;
return changeBufferObjectBindingCalled >= 3 ? 0 : -1;
}
int getErrno() override {
return EINTR;
}
uint32_t changeBufferObjectBindingCalled = 0;
};
auto executionEnvironment = std::make_unique<ExecutionEnvironment>();
executionEnvironment->setDebuggingEnabled();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->calculateMaxOsContextCount();
executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
auto drm = std::make_unique<DrmMockToSucceedBindBufferObject>(*executionEnvironment->rootDeviceEnvironments[0]);
auto drmPtr = drm.get();
executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm.get()));
executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm.release(), 0u);
std::unique_ptr<Device> device(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(), executionEnvironment.release(), 0));
auto osContextCount = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount();
MockBufferObject bo(drmPtr, 3, 0, 0, osContextCount);
auto contextId = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount() / 2;
auto osContext = device->getExecutionEnvironment()->memoryManager->getRegisteredEngines()[contextId].osContext;
auto ret = drmPtr->bindBufferObject(osContext, 0, &bo);
EXPECT_EQ(ret, -1);
EXPECT_EQ(drmPtr->changeBufferObjectBindingCalled, 2u);
}
TEST(DrmBufferObject, givenBufferObjectWhenSecondChangeBufferObjectBindingReturnFailAndErrnoIsENXIOThenItsCalledUntillSuccess) {
struct DrmMockToSucceedBindBufferObject : public DrmMock {
DrmMockToSucceedBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment)
: DrmMock(rootDeviceEnvironment) {}
int changeBufferObjectBinding(OsContext *osContext, uint32_t vmHandleId, BufferObject *bo, bool bind) override {
changeBufferObjectBindingCalled++;
return changeBufferObjectBindingCalled >= 3 ? 0 : -1;
}
int getErrno() override {
return ENXIO;
}
uint32_t changeBufferObjectBindingCalled = 0;
};
auto executionEnvironment = std::make_unique<ExecutionEnvironment>();
executionEnvironment->setDebuggingEnabled();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->calculateMaxOsContextCount();
executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
auto drm = std::make_unique<DrmMockToSucceedBindBufferObject>(*executionEnvironment->rootDeviceEnvironments[0]);
auto drmPtr = drm.get();
executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm.get()));
executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm.release(), 0u);
std::unique_ptr<Device> device(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(), executionEnvironment.release(), 0));
auto osContextCount = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount();
MockBufferObject bo(drmPtr, 3, 0, 0, osContextCount);
auto contextId = device->getExecutionEnvironment()->memoryManager->getRegisteredEnginesCount() / 2;
auto osContext = device->getExecutionEnvironment()->memoryManager->getRegisteredEngines()[contextId].osContext;
auto ret = drmPtr->bindBufferObject(osContext, 0, &bo);
EXPECT_EQ(ret, 0);
EXPECT_EQ(drmPtr->changeBufferObjectBindingCalled, 3u);
}
TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindFailsThenPrintDebugInformationAboutBOBindingResultWithErrno) {
struct DrmMockToFailBindBufferObject : public DrmMock {
DrmMockToFailBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment)
@@ -749,65 +619,3 @@ TEST_F(DrmBufferObjectTest, whenBoRequiresExplicitResidencyThenTheCorrespondingQ
EXPECT_EQ(required, bo.isExplicitResidencyRequired());
}
}
template <int errnoToReturn, int callsToSuccess>
class MyDrmMockCustom : public DrmMockCustom {
public:
MyDrmMockCustom(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMockCustom(rootDeviceEnvironment) {
errnoValue = errnoToReturn;
}
int ioctl(DrmIoctl request, void *arg) override {
ioctlCalledTimes++;
return ioctlCalledTimes >= callsToSuccess ? 0 : -1;
};
int ioctlCalledTimes = 0;
};
using MyDrmMockBufferObjectFixture = DrmBufferObjectFixture<MyDrmMockCustom<0, 1>>;
using MyDrmBufferObjectTest = Test<MyDrmMockBufferObjectFixture>;
TEST_F(MyDrmBufferObjectTest, givenDrmWhenFirstIoctlReturnSuccessThenDoNotRetry) {
ExecObject execObjectsStorage = {};
auto ret = bo->exec(0, 0, 0, false, osContext.get(), 0, 1, nullptr, 0u, &execObjectsStorage, 0, 0);
EXPECT_EQ(ret, 0);
EXPECT_EQ(mock->ioctlCalledTimes, 1);
}
using MyDrmMockBufferObjectFixtureRetryOnce = DrmBufferObjectFixture<MyDrmMockCustom<0, 2>>;
using MyDrmBufferObjectTestRetryOnce = Test<MyDrmMockBufferObjectFixtureRetryOnce>;
TEST_F(MyDrmBufferObjectTestRetryOnce, givenDrmWhenFirstIoctlReturnFailThenRetry) {
ExecObject execObjectsStorage = {};
auto ret = bo->exec(0, 0, 0, false, osContext.get(), 0, 1, nullptr, 0u, &execObjectsStorage, 0, 0);
EXPECT_EQ(ret, 0);
EXPECT_EQ(mock->ioctlCalledTimes, 2);
}
using MyDrmMockBufferObjectFixtureRetryTwice = DrmBufferObjectFixture<MyDrmMockCustom<0, 3>>;
using MyDrmBufferObjectTestRetryTwice = Test<MyDrmMockBufferObjectFixtureRetryTwice>;
TEST_F(MyDrmBufferObjectTestRetryTwice, givenDrmWhenSecondIoctlReturnFailThenRetry) {
ExecObject execObjectsStorage = {};
auto ret = bo->exec(0, 0, 0, false, osContext.get(), 0, 1, nullptr, 0u, &execObjectsStorage, 0, 0);
EXPECT_EQ(ret, 0);
EXPECT_EQ(mock->ioctlCalledTimes, 3);
}
using MyDrmMockBufferObjectFixtureThreeTimes = DrmBufferObjectFixture<MyDrmMockCustom<ESRCH, 4>>;
using MyDrmBufferObjectTestRetryThreeTimes = Test<MyDrmMockBufferObjectFixtureThreeTimes>;
TEST_F(MyDrmBufferObjectTestRetryThreeTimes, givenDrmWhenThirdIoctlReturnFailAndErrnoIsNoENXIOThenDoNotRetry) {
ExecObject execObjectsStorage = {};
auto ret = bo->exec(0, 0, 0, false, osContext.get(), 0, 1, nullptr, 0u, &execObjectsStorage, 0, 0);
EXPECT_EQ(ret, ESRCH);
EXPECT_EQ(mock->ioctlCalledTimes, 3);
}
using MyDrmMockBufferObjectFixtureThreeTimesWithENXIO = DrmBufferObjectFixture<MyDrmMockCustom<ENXIO, 4>>;
using MyDrmBufferObjectTestRetryThreeTimesWithENXIO = Test<MyDrmMockBufferObjectFixtureThreeTimesWithENXIO>;
TEST_F(MyDrmBufferObjectTestRetryThreeTimesWithENXIO, givenDrmWhenThirdIoctlReturnFailAndErrnoIsENXIOThenDoNotRetry) {
ExecObject execObjectsStorage = {};
auto ret = bo->exec(0, 0, 0, false, osContext.get(), 0, 1, nullptr, 0u, &execObjectsStorage, 0, 0);
EXPECT_EQ(ret, 0);
EXPECT_EQ(mock->ioctlCalledTimes, 4);
}