Simplify preemption control on Linux

Change-Id: Ie0896cc8950f7fbb271b710b8bb221eb41ba0445
Signed-off-by: Dunajski, Bartosz <bartosz.dunajski@intel.com>
This commit is contained in:
Dunajski, Bartosz
2018-12-07 15:03:23 +01:00
committed by sys_ocldev
parent 9e53740130
commit f5508ed2d7
11 changed files with 63 additions and 105 deletions

2
Jenkinsfile vendored
View File

@@ -1,5 +1,5 @@
#!groovy
dependenciesRevision='0069cbdd1559b47c9de98ca934b334b12fa59703-1174'
strategy='EQUAL'
allowedCD=274
allowedCD=273
allowedF=4

View File

@@ -28,8 +28,9 @@ const DeviceDescriptor deviceDescriptorTable[] = {
static std::array<Drm *, 1> drms = {{nullptr}};
Drm::~Drm() {
if (lowPriorityContextId)
contextDestroy();
if (lowPriorityContextId != 0) {
destroyLowPriorityContext();
}
close(fd);
fd = -1;
}

View File

@@ -129,49 +129,34 @@ bool Drm::is48BitAddressRangeSupported() {
return (ret == 0) && (value == 3);
}
bool Drm::hasPreemption() {
void Drm::checkPreemptionSupport() {
#if defined(I915_PARAM_HAS_PREEMPTION)
int value = 0;
auto ret = getParam(I915_PARAM_HAS_PREEMPTION, &value);
if (ret == 0 && value == 1) {
return contextCreate() && setLowPriority();
}
preemptionSupported = (ret == 0 && value == 1);
#endif
return false;
}
bool Drm::setLowPriority() {
#if defined(I915_PARAM_HAS_PREEMPTION)
struct drm_i915_gem_context_param gcp = {};
void Drm::createLowPriorityContext() {
drm_i915_gem_context_create gcc = {};
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &gcc);
UNRECOVERABLE_IF(retVal != 0);
lowPriorityContextId = gcc.ctx_id;
drm_i915_gem_context_param gcp = {};
gcp.ctx_id = lowPriorityContextId;
gcp.param = I915_CONTEXT_PARAM_PRIORITY;
gcp.value = -1023;
int ret = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &gcp);
if (ret == 0) {
return true;
}
#endif
return false;
retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &gcp);
UNRECOVERABLE_IF(retVal != 0);
}
bool Drm::contextCreate() {
#if defined(I915_PARAM_HAS_PREEMPTION)
drm_i915_gem_context_create gcc = {};
if (ioctl(DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &gcc) == 0) {
lowPriorityContextId = gcc.ctx_id;
return true;
}
#endif
return false;
}
void Drm::contextDestroy() {
#if defined(I915_PARAM_HAS_PREEMPTION)
void Drm::destroyLowPriorityContext() {
drm_i915_gem_context_destroy destroy = {};
destroy.ctx_id = lowPriorityContextId;
ioctl(DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
#endif
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
UNRECOVERABLE_IF(retVal != 0);
}
int Drm::getEuTotal(int &euTotal) {

View File

@@ -54,11 +54,11 @@ class Drm {
int getMinEuInPool(int &minEUinPool);
bool is48BitAddressRangeSupported();
MOCKABLE_VIRTUAL bool hasPreemption();
bool setLowPriority();
bool isPreemptionSupported() const { return preemptionSupported; }
MOCKABLE_VIRTUAL void checkPreemptionSupport();
int getFileDescriptor() const { return fd; }
bool contextCreate();
void contextDestroy();
void createLowPriorityContext();
void destroyLowPriorityContext();
void setGtType(GTTYPE eGtType) { this->eGtType = eGtType; }
GTTYPE getGtType() const { return this->eGtType; }
@@ -68,6 +68,7 @@ class Drm {
protected:
bool useSimplifiedMocsTable = false;
bool preemptionSupported = false;
int fd;
int deviceId;
int revisionId;

View File

@@ -160,7 +160,11 @@ int HwInfoConfig::configureHwInfo(const HardwareInfo *inHwInfo, HardwareInfo *ou
outHwInfo->capabilityTable.ftrRenderCompressedBuffers = false;
outHwInfo->capabilityTable.ftrRenderCompressedImages = false;
bool preemption = drm->hasPreemption();
drm->checkPreemptionSupport();
bool preemption = drm->isPreemptionSupported();
if (preemption) {
drm->createLowPriorityContext();
}
preemption = hwHelper.setupPreemptionRegisters(outHwInfo, preemption);
PreemptionHelper::adjustDefaultPreemptionMode(outHwInfo->capabilityTable,
static_cast<bool>(outHwInfo->pSkuTable->ftrGpGpuMidThreadLevelPreempt) && preemption,

View File

@@ -16,11 +16,7 @@ GEN10TEST_F(DeviceFactoryLinuxTestCnl, queryWhitelistedPreemptionRegister) {
bool success = DeviceFactory::getDevices(&hwInfo, numDevices, executionEnvironment);
EXPECT_TRUE(success);
#if defined(I915_PARAM_HAS_PREEMPTION)
EXPECT_TRUE(hwInfo->capabilityTable.whitelistedRegisters.csChicken1_0x2580);
#else
EXPECT_FALSE(hwInfo->capabilityTable.whitelistedRegisters.csChicken1_0x2580);
#endif
DeviceFactory::releaseDevices();
}

View File

@@ -16,11 +16,7 @@ GEN9TEST_F(DeviceFactoryLinuxTestSkl, queryWhitelistedPreemptionRegister) {
bool success = DeviceFactory::getDevices(&hwInfo, numDevices, executionEnvironment);
EXPECT_TRUE(success);
#if defined(I915_PARAM_HAS_PREEMPTION)
EXPECT_TRUE(hwInfo->capabilityTable.whitelistedRegisters.csChicken1_0x2580);
#else
EXPECT_FALSE(hwInfo->capabilityTable.whitelistedRegisters.csChicken1_0x2580);
#endif
DeviceFactory::releaseDevices();
}

View File

@@ -264,25 +264,26 @@ TEST_F(DrmTests, givenKernelSupportingTurboPatchWhenDeviceIsCreatedThenSimplifie
EXPECT_FALSE(drm->getSimplifiedMocsTableUsage());
}
#if defined(I915_PARAM_HAS_PREEMPTION)
TEST_F(DrmTests, checkPreemption) {
auto drm = DrmWrap::createDrm(0);
EXPECT_NE(drm, nullptr);
bool ret = drm->hasPreemption();
EXPECT_EQ(ret, true);
drm->checkPreemptionSupport();
#if defined(I915_PARAM_HAS_PREEMPTION)
EXPECT_TRUE(drm->isPreemptionSupported());
#else
EXPECT_FALSE(drm->isPreemptionSupported());
#endif
DrmWrap::closeDevice(0);
drm = DrmWrap::get(0);
EXPECT_EQ(drm, nullptr);
}
#endif
TEST_F(DrmTests, failOnContextCreate) {
auto drm = DrmWrap::createDrm(0);
EXPECT_NE(drm, nullptr);
failOnContextCreate = -1;
bool ret = drm->hasPreemption();
EXPECT_EQ(ret, false);
EXPECT_THROW(drm->createLowPriorityContext(), std::exception);
EXPECT_FALSE(drm->isPreemptionSupported());
failOnContextCreate = 0;
DrmWrap::closeDevice(0);
@@ -294,8 +295,8 @@ TEST_F(DrmTests, failOnSetPriority) {
auto drm = DrmWrap::createDrm(0);
EXPECT_NE(drm, nullptr);
failOnSetPriority = -1;
bool ret = drm->hasPreemption();
EXPECT_EQ(ret, false);
EXPECT_THROW(drm->createLowPriorityContext(), std::exception);
EXPECT_FALSE(drm->isPreemptionSupported());
failOnSetPriority = 0;
DrmWrap::closeDevice(0);

View File

@@ -19,6 +19,10 @@
using namespace OCLRT;
#if !defined(I915_PARAM_HAS_PREEMPTION)
#define I915_PARAM_HAS_PREEMPTION 0x806
#endif
static const int mockFd = 33;
// Mock DRM class that responds to DRM_IOCTL_I915_GETPARAMs
class DrmMock : public Drm {
@@ -32,7 +36,7 @@ class DrmMock : public Drm {
sysFsDefaultGpuPath = sysFsDefaultGpuPathToRestore;
}
}
virtual inline int ioctl(unsigned long request, void *arg) {
int ioctl(unsigned long request, void *arg) override {
if ((request == DRM_IOCTL_I915_GETPARAM) && (arg != nullptr)) {
drm_i915_getparam_t *gp = (drm_i915_getparam_t *)arg;
if (false
@@ -194,20 +198,8 @@ class DrmMock : public Drm {
void setDeviceID(int deviceId) { this->deviceId = deviceId; }
void setDeviceRevID(int revisionId) { this->revisionId = revisionId; }
bool hasPreemption() {
#if defined(I915_PARAM_HAS_PREEMPTION)
drm_i915_getparam_t gp;
int value = 0;
gp.value = &value;
gp.param = I915_PARAM_HAS_PREEMPTION;
int ret = ioctl(DRM_IOCTL_I915_GETPARAM, &gp);
if (ret == 0 && *gp.value == 1) {
return contextCreate() && setLowPriority();
}
return false;
#else
return this->StoredMockPreemptionSupport == 1 ? true : false;
#endif
void checkPreemptionSupport() override {
preemptionSupported = StoredPreemptionSupport;
}
int StoredEUVal = -1;
@@ -224,8 +216,7 @@ class DrmMock : public Drm {
int StoredRetValForPooledEU = 0;
int StoredRetValForMinEUinPool = 0;
int StoredPPGTT = 3;
int StoredPreemptionSupport = 1;
int StoredMockPreemptionSupport = 0;
int StoredPreemptionSupport = 0;
int StoredExecSoftPin = 0;
uint32_t StoredCtxId = 1;

View File

@@ -125,13 +125,15 @@ TEST(DrmTest, GivenDrmWhenAskedFor48BitAddressCorrectValueReturned) {
delete pDrm;
}
#if defined(I915_PARAM_HAS_PREEMPTION)
TEST(DrmTest, GivenDrmWhenAskedForPreemptionCorrectValueReturned) {
DrmMock *pDrm = new DrmMock;
pDrm->StoredPreemptionSupport = 1;
EXPECT_TRUE(pDrm->hasPreemption());
pDrm->checkPreemptionSupport();
EXPECT_TRUE(pDrm->isPreemptionSupported());
pDrm->StoredPreemptionSupport = 0;
EXPECT_FALSE(pDrm->hasPreemption());
pDrm->checkPreemptionSupport();
EXPECT_FALSE(pDrm->isPreemptionSupported());
delete pDrm;
}
@@ -140,7 +142,7 @@ TEST(DrmTest, GivenDrmWhenAskedForContextThatPassedThenValidContextIdsReturned)
EXPECT_EQ(0u, pDrm->lowPriorityContextId);
pDrm->StoredRetVal = 0;
pDrm->StoredCtxId = 2;
EXPECT_TRUE(pDrm->contextCreate());
pDrm->createLowPriorityContext();
EXPECT_EQ(2u, pDrm->lowPriorityContextId);
pDrm->StoredRetVal = 0;
pDrm->StoredCtxId = 1;
@@ -150,36 +152,17 @@ TEST(DrmTest, GivenDrmWhenAskedForContextThatPassedThenValidContextIdsReturned)
TEST(DrmTest, GivenDrmWhenAskedForContextThatFailsThenFalseIsReturned) {
DrmMock *pDrm = new DrmMock;
pDrm->StoredRetVal = -1;
EXPECT_FALSE(pDrm->contextCreate());
EXPECT_THROW(pDrm->createLowPriorityContext(), std::exception);
pDrm->StoredRetVal = 0;
delete pDrm;
}
TEST(DrmTest, GivenDrmWhenAskedForContextWithLowPriorityThatFailsThenFalseIsReturned) {
DrmMock *pDrm = new DrmMock;
EXPECT_TRUE(pDrm->contextCreate());
pDrm->StoredRetVal = -1;
EXPECT_FALSE(pDrm->setLowPriority());
pDrm->StoredRetVal = 0;
delete pDrm;
}
#else
TEST(DrmTest, GivenDrmWhenAskedForContextWithLowPriorityThenFalseIsReturned) {
DrmMock drmMock;
EXPECT_FALSE(drmMock.contextCreate());
}
TEST(DrmTest, GivenDrmWhenContextDestroyIsCalledThenThereAreNoLeaksOrCrashes) {
DrmMock drmMock;
drmMock.contextDestroy();
drmMock.createLowPriorityContext();
drmMock.destroyLowPriorityContext();
}
TEST(DrmTest, GivenDrmWhenSetContextPriorityIsCalledThenFalseIsReturned) {
DrmMock drmMock;
EXPECT_FALSE(drmMock.setLowPriority());
}
#endif
TEST(DrmTest, getExecSoftPin) {
DrmMock *pDrm = new DrmMock;
int execSoftPin = 0;

View File

@@ -249,81 +249,81 @@ TEST_F(HwInfoConfigTestLinuxDummy, dummyNegativeUnknownDeviceId) {
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledMidThreadOn) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidThread;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = hwConfigTestMidThreadBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::MidThread, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledThreadGroupOn) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidThread;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = hwConfigTestThreadGroupBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::ThreadGroup, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledMidBatchOn) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidThread;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = hwConfigTestMidBatchBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::MidBatch, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledNoPreemption) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidThread;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = 1;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::Disabled, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmDisabledAllPreemption) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidThread;
drm->StoredPreemptionSupport = 0;
drm->StoredMockPreemptionSupport = 0;
drm->StoredDeviceID = hwConfigTestMidThreadBit | hwConfigTestThreadGroupBit | hwConfigTestMidBatchBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::Disabled, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_FALSE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledAllPreemptionDriverThreadGroup) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::ThreadGroup;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = hwConfigTestMidThreadBit | hwConfigTestThreadGroupBit | hwConfigTestMidBatchBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::ThreadGroup, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledAllPreemptionDriverMidBatch) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::MidBatch;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = hwConfigTestMidThreadBit | hwConfigTestThreadGroupBit | hwConfigTestMidBatchBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::MidBatch, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, dummyConfigPreemptionDrmEnabledAllPreemptionDriverDisabled) {
pInHwInfo->capabilityTable.defaultPreemptionMode = PreemptionMode::Disabled;
drm->StoredPreemptionSupport = 1;
drm->StoredMockPreemptionSupport = 1;
drm->StoredDeviceID = hwConfigTestMidThreadBit | hwConfigTestThreadGroupBit | hwConfigTestMidBatchBit;
int ret = hwConfig.configureHwInfo(pInHwInfo, &outHwInfo, osInterface);
EXPECT_EQ(0, ret);
EXPECT_EQ(PreemptionMode::Disabled, outHwInfo.capabilityTable.defaultPreemptionMode);
EXPECT_TRUE(drm->isPreemptionSupported());
}
TEST_F(HwInfoConfigTestLinuxDummy, givenPlatformEnabledFtrCompressionWhenInitializingThenForceDisable) {