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,7 +147,6 @@ int BufferObject::exec(uint32_t used, size_t startOffset, unsigned int flags, bo
int ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue); int ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
if (ret != 0) { if (ret != 0) {
do {
int err = this->drm->getErrno(); int err = this->drm->getErrno();
if (err == EOPNOTSUPP) { 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)); PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(I915_GEM_EXECBUFFER2) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
@@ -156,6 +155,7 @@ int BufferObject::exec(uint32_t used, size_t startOffset, unsigned int flags, bo
evictUnusedAllocations(false, true); evictUnusedAllocations(false, true);
ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue); ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
}
if (ret != 0) { if (ret != 0) {
const auto status = evictUnusedAllocations(true, true); const auto status = evictUnusedAllocations(true, true);
@@ -166,8 +166,6 @@ int BufferObject::exec(uint32_t used, size_t startOffset, unsigned int flags, bo
ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue); ret = ioctlHelper->execBuffer(&execbuf, completionGpuAddress, completionValue);
} }
} while (ret != 0 && this->drm->getErrno() == ENXIO);
}
if (ret == 0) { if (ret == 0) {
return 0; return 0;

View File

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

View File

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

View File

@@ -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"); 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) { TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindFailsThenPrintDebugInformationAboutBOBindingResultWithErrno) {
struct DrmMockToFailBindBufferObject : public DrmMock { struct DrmMockToFailBindBufferObject : public DrmMock {
DrmMockToFailBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment) DrmMockToFailBindBufferObject(RootDeviceEnvironment &rootDeviceEnvironment)
@@ -749,65 +619,3 @@ TEST_F(DrmBufferObjectTest, whenBoRequiresExplicitResidencyThenTheCorrespondingQ
EXPECT_EQ(required, bo.isExplicitResidencyRequired()); 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);
}