Do not call DebuggerOpen ioctl again on EBUSY

Resolves: NEO-7429

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2022-10-18 18:37:33 +00:00
committed by Compute-Runtime-Automation
parent abe4e0cb91
commit 5bd4b9eb48
8 changed files with 128 additions and 3 deletions

View File

@ -60,7 +60,7 @@ void Drm::queryAndSetVmBindPatIndexProgrammingSupport() {
int Drm::ioctl(DrmIoctl request, void *arg) {
auto requestValue = getIoctlRequestValue(request, ioctlHelper.get());
int ret;
int returnedErrno;
int returnedErrno = 0;
SYSTEM_ENTER();
do {
auto measureTime = DebugManager.flags.PrintIoctlTimes.get();
@ -78,7 +78,9 @@ int Drm::ioctl(DrmIoctl request, void *arg) {
}
ret = SysCalls::ioctl(getFileDescriptor(), requestValue, arg);
returnedErrno = errno;
if (ret != 0) {
returnedErrno = getErrno();
}
if (measureTime) {
end = std::chrono::steady_clock::now();
@ -108,7 +110,7 @@ int Drm::ioctl(DrmIoctl request, void *arg) {
}
}
} while (ret == -1 && (returnedErrno == EINTR || returnedErrno == EAGAIN || returnedErrno == EBUSY || returnedErrno == -EBUSY));
} while (ret == -1 && checkIfIoctlReinvokeRequired(returnedErrno, request, ioctlHelper.get()));
SYSTEM_LEAVE(request);
return ret;
}

View File

@ -29,6 +29,13 @@ unsigned int getIoctlRequestValue(DrmIoctl ioctlRequest, IoctlHelper *ioctlHelpe
}
}
bool checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest, IoctlHelper *ioctlHelper) {
if (ioctlHelper) {
return ioctlHelper->checkIfIoctlReinvokeRequired(error, ioctlRequest);
}
return (error == EINTR || error == EAGAIN || error == EBUSY || error == -EBUSY);
}
int getDrmParamValue(DrmParam drmParam, IoctlHelper *ioctlHelper) {
if (ioctlHelper) {
return ioctlHelper->getDrmParamValue(drmParam);

View File

@ -207,6 +207,14 @@ struct DrmVersion {
char *desc;
};
struct DrmDebuggerOpen {
uint64_t pid;
uint32_t flags;
uint32_t version;
uint64_t events;
uint64_t extensions;
};
enum class DrmIoctl {
GemExecbuffer2,
GemWait,
@ -299,5 +307,6 @@ unsigned int getIoctlRequestValue(DrmIoctl ioctlRequest, IoctlHelper *ioctlHelpe
int getDrmParamValue(DrmParam drmParam, IoctlHelper *ioctlHelper);
std::string getDrmParamString(DrmParam param, IoctlHelper *ioctlHelper);
std::string getIoctlString(DrmIoctl ioctlRequest, IoctlHelper *ioctlHelper);
bool checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest, IoctlHelper *ioctlHelper);
} // namespace NEO

View File

@ -369,4 +369,7 @@ std::string IoctlHelper::getFileForMaxMemoryFrequencyOfSubDevice(int subDeviceId
return "/gt/gt" + std::to_string(subDeviceId) + "/mem_RP0_freq_mhz";
}
bool IoctlHelper::checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest) const {
return (error == EINTR || error == EAGAIN || error == EBUSY || error == -EBUSY);
}
} // namespace NEO

View File

@ -114,6 +114,7 @@ class IoctlHelper {
virtual std::string getDrmParamString(DrmParam param) const = 0;
virtual std::string getIoctlString(DrmIoctl ioctlRequest) const = 0;
virtual bool checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest) const;
virtual std::vector<MemoryRegion> translateToMemoryRegions(const std::vector<uint8_t> &regionInfo);
virtual uint32_t createDrmContext(Drm &drm, OsContextLinux &osContext, uint32_t drmVmId, uint32_t deviceIndex);
@ -254,6 +255,7 @@ class IoctlHelperPrelim20 : public IoctlHelper {
int getDrmParamValue(DrmParam drmParam) const override;
std::string getDrmParamString(DrmParam param) const override;
std::string getIoctlString(DrmIoctl ioctlRequest) const override;
bool checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest) const override;
};
} // namespace NEO

View File

@ -645,6 +645,16 @@ std::string IoctlHelperPrelim20::getIoctlString(DrmIoctl ioctlRequest) const {
}
}
bool IoctlHelperPrelim20::checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest) const {
switch (ioctlRequest) {
case DrmIoctl::DebuggerOpen:
return (error == EINTR || error == EAGAIN);
default:
break;
}
return IoctlHelper::checkIfIoctlReinvokeRequired(error, ioctlRequest);
}
static_assert(sizeof(MemoryClassInstance) == sizeof(prelim_drm_i915_gem_memory_class_instance));
static_assert(offsetof(MemoryClassInstance, memoryClass) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_class));
static_assert(offsetof(MemoryClassInstance, memoryInstance) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_instance));

View File

@ -206,6 +206,68 @@ TEST(DrmQueryTest, WhenCallingIsDebugAttachAvailableThenReturnValueIsTrue) {
EXPECT_TRUE(drm.isDebugAttachAvailable());
}
TEST(DrmPrelimTest, GivenDebuggerOpenIoctlWhenErrorEbusyReturnedThenErrorIsReturnedWithoutReinvokingIoctl) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]};
drm.allowDebugAttachCallBase = true;
VariableBackup<decltype(SysCalls::sysCallsIoctl)> mockIoctl(&SysCalls::sysCallsIoctl, [](int fileDescriptor, unsigned long int request, void *arg) -> int {
return -1;
});
DrmDebuggerOpen open = {};
open.pid = 1;
open.events = 0;
drm.context.debuggerOpenRetval = -1;
drm.errnoRetVal = EBUSY;
auto ret = drm.Drm::ioctl(DrmIoctl::DebuggerOpen, &open);
EXPECT_EQ(-1, ret);
}
TEST(DrmPrelimTest, GivenDebuggerOpenIoctlWhenErrorEAgainOrEIntrReturnedThenIoctlIsCalledAgain) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]};
drm.allowDebugAttachCallBase = true;
drm.baseErrno = false;
DrmDebuggerOpen open = {};
open.pid = 1;
open.events = 0;
{
VariableBackup<decltype(SysCalls::sysCallsIoctl)> mockIoctl(&SysCalls::sysCallsIoctl, [](int fileDescriptor, unsigned long int request, void *arg) -> int {
static int callCount = 3;
if (callCount > 0) {
callCount--;
return -1;
}
return 0;
});
drm.errnoRetVal = EAGAIN;
auto ret = drm.Drm::ioctl(DrmIoctl::DebuggerOpen, &open);
EXPECT_EQ(0, ret);
}
{
VariableBackup<decltype(SysCalls::sysCallsIoctl)> mockIoctl(&SysCalls::sysCallsIoctl, [](int fileDescriptor, unsigned long int request, void *arg) -> int {
static int callCount = 3;
if (callCount > 0) {
callCount--;
return -1;
}
return 0;
});
drm.ioctlCallsCount = 0;
drm.errnoRetVal = EINTR;
auto ret = drm.Drm::ioctl(DrmIoctl::DebuggerOpen, &open);
EXPECT_EQ(0, ret);
}
}
struct BufferObjectMock : public BufferObject {
using BufferObject::BufferObject;
using BufferObject::fillExecObject;

View File

@ -1404,6 +1404,36 @@ TEST(DrmWrapperTest, WhenGettingDrmParamValueStringThenProperStringIsReturned) {
EXPECT_THROW(getDrmParamString(DrmParam::EngineClassRender, &ioctlHelper), std::runtime_error);
}
TEST(DrmWrapperTest, givenEAgainOrEIntrOrEBusyWhenCheckingIfReinvokeRequiredThenTrueIsReturned) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]};
MockIoctlHelper ioctlHelper{drm};
EXPECT_TRUE(checkIfIoctlReinvokeRequired(EAGAIN, DrmIoctl::Getparam, &ioctlHelper));
EXPECT_TRUE(checkIfIoctlReinvokeRequired(EINTR, DrmIoctl::Getparam, &ioctlHelper));
EXPECT_TRUE(checkIfIoctlReinvokeRequired(EBUSY, DrmIoctl::Getparam, &ioctlHelper));
EXPECT_TRUE(checkIfIoctlReinvokeRequired(-EBUSY, DrmIoctl::Getparam, &ioctlHelper));
}
TEST(DrmWrapperTest, givenNoIoctlHelperAndEAgainOrEIntrOrEBusyWhenCheckingIfReinvokeRequiredThenTrueIsReturned) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]};
EXPECT_TRUE(checkIfIoctlReinvokeRequired(EAGAIN, DrmIoctl::Getparam, nullptr));
EXPECT_TRUE(checkIfIoctlReinvokeRequired(EINTR, DrmIoctl::Getparam, nullptr));
EXPECT_TRUE(checkIfIoctlReinvokeRequired(EBUSY, DrmIoctl::Getparam, nullptr));
EXPECT_TRUE(checkIfIoctlReinvokeRequired(-EBUSY, DrmIoctl::Getparam, nullptr));
}
TEST(DrmWrapperTest, givenErrorWhenCheckingIfReinvokeRequiredThenFalseIsReturned) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]};
MockIoctlHelper ioctlHelper{drm};
EXPECT_FALSE(checkIfIoctlReinvokeRequired(ENOENT, DrmIoctl::Getparam, &ioctlHelper));
EXPECT_FALSE(checkIfIoctlReinvokeRequired(ENOENT, DrmIoctl::Getparam, nullptr));
}
TEST(IoctlHelperTest, whenGettingDrmParamValueThenProperValueIsReturned) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]};