mirror of
https://github.com/intel/compute-runtime.git
synced 2025-09-15 13:01:45 +08:00
WSL - fixing resource cleanup on process shutdown
Resolves issues with coexistance of NEO L0 and NEO OCL libraries within a single process running in WSL and using WDDM GPU PV Signed-off-by: Jaroslaw Chodor <jaroslaw.chodor@intel.com>
This commit is contained in:

committed by
Compute-Runtime-Automation

parent
c77fe0bffc
commit
c4e802f01b
@ -875,3 +875,11 @@ TEST(DrmQueryTest, GivenRpsMaxFreqFileDoesntExistWhenFrequencyIsQueriedThenFallb
|
||||
|
||||
EXPECT_EQ(expectedMaxFrequency, maxFrequency);
|
||||
}
|
||||
|
||||
TEST(DrmTest, whenCheckedIfResourcesCleanupCanBeSkippedThenReturnsFalse) {
|
||||
auto executionEnvironment = std::make_unique<ExecutionEnvironment>();
|
||||
executionEnvironment->prepareRootDeviceEnvironments(1);
|
||||
DrmMock *pDrm = new DrmMock(*executionEnvironment->rootDeviceEnvironments[0]);
|
||||
EXPECT_FALSE(pDrm->skipResourceCleanup());
|
||||
delete pDrm;
|
||||
}
|
||||
|
@ -211,7 +211,15 @@ bool CommandStreamReceiver::isRcs() const {
|
||||
return this->osContext->getEngineType() == aub_stream::ENGINE_RCS;
|
||||
}
|
||||
|
||||
bool CommandStreamReceiver::skipResourceCleanup() const {
|
||||
return this->getOSInterface() && this->getOSInterface()->getDriverModel() && this->getOSInterface()->getDriverModel()->skipResourceCleanup();
|
||||
}
|
||||
|
||||
void CommandStreamReceiver::cleanupResources() {
|
||||
if (this->skipResourceCleanup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
waitForTaskCountAndCleanAllocationList(this->latestFlushedTaskCount, TEMPORARY_ALLOCATION);
|
||||
waitForTaskCountAndCleanAllocationList(this->latestFlushedTaskCount, REUSABLE_ALLOCATION);
|
||||
|
||||
|
@ -288,6 +288,8 @@ class CommandStreamReceiver {
|
||||
return activePartitions;
|
||||
}
|
||||
|
||||
bool skipResourceCleanup() const;
|
||||
|
||||
std::unique_ptr<GmmPageTableMngr> pageTableManager;
|
||||
|
||||
protected:
|
||||
|
@ -36,10 +36,15 @@ Device::Device(ExecutionEnvironment *executionEnvironment)
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
getMemoryManager()->freeGraphicsMemory(rtMemoryBackedBuffer);
|
||||
rtMemoryBackedBuffer = nullptr;
|
||||
if (false == commandStreamReceivers.empty()) {
|
||||
if (commandStreamReceivers[0]->skipResourceCleanup()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_BREAK_IF(nullptr == executionEnvironment->memoryManager.get());
|
||||
getMemoryManager()->freeGraphicsMemory(rtMemoryBackedBuffer);
|
||||
rtMemoryBackedBuffer = nullptr;
|
||||
|
||||
if (performanceCounters) {
|
||||
performanceCounters->shutdown();
|
||||
|
@ -83,6 +83,10 @@ class DriverModel : public NonCopyableClass {
|
||||
return std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
virtual bool skipResourceCleanup() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
DriverModelType driverModelType;
|
||||
};
|
||||
|
@ -87,6 +87,7 @@ set(NEO_CORE_OS_INTERFACE_WDDM
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/set_gmm_input_args_${DRIVER_MODEL}.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/max_mem_alloc_size_${DRIVER_MODEL}.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/helper_${DRIVER_MODEL}.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/skip_resource_cleanup_${DRIVER_MODEL}.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/wddm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/wddm.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wddm/wddm_defs.h
|
||||
|
@ -39,7 +39,7 @@ void OsContextWin::initializeContext() {
|
||||
};
|
||||
|
||||
OsContextWin::~OsContextWin() {
|
||||
if (contextInitialized) {
|
||||
if (contextInitialized && (false == this->wddm.skipResourceCleanup())) {
|
||||
wddm.getWddmInterface()->destroyHwQueue(hardwareQueue.handle);
|
||||
wddm.getWddmInterface()->destroyMonitorFence(residencyController.getMonitoredFence());
|
||||
wddm.destroyContext(wddmContextHandle);
|
||||
|
@ -159,7 +159,7 @@ bool ensureGpuAddressRangeIsReserved(uint64_t address, size_t size, D3DKMT_HANDL
|
||||
rangeDesc.MaximumAddress = alignUp(address + size, MemoryConstants::pageSize64k);
|
||||
rangeDesc.Size = MemoryConstants::pageSize64k;
|
||||
status = gdi.reserveGpuVirtualAddress(&rangeDesc);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
if (status == STATUS_SUCCESS) {
|
||||
DEBUG_BREAK_IF(true);
|
||||
return false;
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/os_interface/windows/gdi_interface.h"
|
||||
#include "shared/source/os_interface/windows/wddm/wddm.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Wddm::skipResourceCleanup() const {
|
||||
D3DKMT_GETDEVICESTATE deviceState = {};
|
||||
deviceState.hDevice = device;
|
||||
deviceState.StateType = D3DKMT_DEVICESTATE_PRESENT;
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
status = getGdi()->getDeviceState(&deviceState);
|
||||
return status != STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/os_interface/windows/wddm/wddm.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Wddm::skipResourceCleanup() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
@ -189,6 +189,7 @@ class Wddm : public DriverModel {
|
||||
PhysicalDevicePciBusInfo getPciBusInfo() const override;
|
||||
|
||||
size_t getMaxMemAllocSize() const override;
|
||||
bool skipResourceCleanup() const override;
|
||||
|
||||
static std::vector<std::unique_ptr<HwDeviceId>> discoverDevices(ExecutionEnvironment &executionEnvironment);
|
||||
|
||||
|
@ -118,6 +118,9 @@ struct GdiMockConfig {
|
||||
D3DKMT_LOCK2 receivedLock2Args = {};
|
||||
D3DKMT_DESTROYALLOCATION2 receivedDestroyAllocation2Args = {};
|
||||
uint32_t mockAllocationHandle = 7U;
|
||||
|
||||
D3DKMT_GETDEVICESTATE receivedGetDeviceStateArgs = {};
|
||||
GdiMockCallbackWithReturn getDeviceStateClb = {};
|
||||
} gdiMockConfig;
|
||||
|
||||
NTSTATUS __stdcall reserveDeviceAddressSpaceMock(D3DDDI_RESERVEGPUVIRTUALADDRESS *arg) {
|
||||
@ -185,6 +188,15 @@ NTSTATUS __stdcall escapeMock(const D3DKMT_ESCAPE *arg) {
|
||||
return gdiMockConfig.escapeClb.returnValue;
|
||||
}
|
||||
|
||||
NTSTATUS __stdcall getDeviceStateMock(D3DKMT_GETDEVICESTATE *arg) {
|
||||
gdiMockConfig.receivedGetDeviceStateArgs = *arg;
|
||||
gdiMockConfig.getDeviceStateClb.callCount += 1;
|
||||
if (gdiMockConfig.getDeviceStateClb.callback) {
|
||||
gdiMockConfig.getDeviceStateClb.callback();
|
||||
}
|
||||
return gdiMockConfig.getDeviceStateClb.returnValue;
|
||||
}
|
||||
|
||||
struct WddmLinuxTest : public ::testing::Test {
|
||||
void SetUp() override {
|
||||
mockRootDeviceEnvironment = std::make_unique<NEO::MockRootDeviceEnvironment>(mockExecEnv);
|
||||
@ -248,9 +260,16 @@ TEST_F(WddmLinuxConfigureDeviceAddressSpaceTest, givenPreReservedSvmAddressSpace
|
||||
}
|
||||
|
||||
this->osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock;
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = -2;
|
||||
gdiMockConfig.reserveGpuVaClb.callback = []() { gdiMockConfig.reserveGpuVaClb.returnValue += 1; };
|
||||
auto cantReserveWholeGpuVAButCanReservePortion = []() {
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = (gdiMockConfig.reserveGpuVaClb.callCount == 1) ? -1 : 0;
|
||||
};
|
||||
gdiMockConfig.reserveGpuVaClb.callback = cantReserveWholeGpuVAButCanReservePortion;
|
||||
bool success = this->wddm->configureDeviceAddressSpace();
|
||||
EXPECT_FALSE(success);
|
||||
|
||||
auto cantReserveWholeGpuVAAndCantReservePortion = []() { gdiMockConfig.reserveGpuVaClb.returnValue = -1; };
|
||||
gdiMockConfig.reserveGpuVaClb.callback = cantReserveWholeGpuVAAndCantReservePortion;
|
||||
success = this->wddm->configureDeviceAddressSpace();
|
||||
EXPECT_TRUE(success);
|
||||
|
||||
auto svmSize = this->getMaxSvmSize();
|
||||
@ -261,19 +280,6 @@ TEST_F(WddmLinuxConfigureDeviceAddressSpaceTest, givenPreReservedSvmAddressSpace
|
||||
EXPECT_EQ(wddm->getAdapter(), gdiMockConfig.receivedReserveGpuVaArgs.hAdapter);
|
||||
}
|
||||
|
||||
TEST_F(WddmLinuxConfigureDeviceAddressSpaceTest, givenSvmAddressSpaceWhenCouldNotReserveGpuVAForSvmThenFail) {
|
||||
if (NEO::hardwareInfoTable[productFamily]->capabilityTable.gpuAddressSpace < MemoryConstants::max64BitAppAddress) {
|
||||
GTEST_SKIP();
|
||||
}
|
||||
|
||||
osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock;
|
||||
this->osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock;
|
||||
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = -1;
|
||||
bool success = this->wddm->configureDeviceAddressSpace();
|
||||
EXPECT_FALSE(success);
|
||||
}
|
||||
|
||||
TEST_F(WddmLinuxConfigureDeviceAddressSpaceTest, givenNonSvmAddressSpaceThenReserveGpuVAForUSMIsNotCalled) {
|
||||
if (NEO::hardwareInfoTable[productFamily]->capabilityTable.gpuAddressSpace >= MemoryConstants::max64BitAppAddress) {
|
||||
GTEST_SKIP();
|
||||
@ -531,10 +537,13 @@ TEST_F(WddmLinuxConfigureReduced48bitDeviceAddressSpaceTest, givenTwoSvmAddressS
|
||||
}
|
||||
|
||||
this->wddm->featureTable->ftrCCSRing = 1;
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = -1;
|
||||
|
||||
osEnvironment->gdi->escape = escapeMock;
|
||||
osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock;
|
||||
auto cantReserveWholeGpuVAButCanReservePortion = []() {
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = (gdiMockConfig.reserveGpuVaClb.callCount == 1) ? -1 : 0;
|
||||
};
|
||||
gdiMockConfig.reserveGpuVaClb.callback = cantReserveWholeGpuVAButCanReservePortion;
|
||||
bool success = this->wddm->configureDeviceAddressSpace();
|
||||
EXPECT_FALSE(success);
|
||||
EXPECT_EQ(1U, this->wddm->validAddressRangeReservations.size());
|
||||
@ -549,14 +558,12 @@ TEST_F(WddmLinuxConfigureReduced48bitDeviceAddressSpaceTest, givenTwoSvmAddressS
|
||||
}
|
||||
|
||||
this->wddm->featureTable->ftrCCSRing = 1;
|
||||
gdiMockConfig.reserveGpuVaClb.callback = []() {
|
||||
if (gdiMockConfig.reserveGpuVaClb.callCount > 1) {
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = -1;
|
||||
};
|
||||
};
|
||||
|
||||
osEnvironment->gdi->escape = escapeMock;
|
||||
osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock;
|
||||
auto cantReserveWholeGpuVAOfSecondButCanReservePortionOfSecont = []() {
|
||||
gdiMockConfig.reserveGpuVaClb.returnValue = (gdiMockConfig.reserveGpuVaClb.callCount == 2) ? -1 : 0;
|
||||
};
|
||||
gdiMockConfig.reserveGpuVaClb.callback = cantReserveWholeGpuVAOfSecondButCanReservePortionOfSecont;
|
||||
bool success = this->wddm->configureDeviceAddressSpace();
|
||||
EXPECT_FALSE(success);
|
||||
EXPECT_EQ(1U, this->wddm->validAddressRangeReservations.size());
|
||||
@ -605,6 +612,20 @@ TEST_F(WddmLinuxTest, givenRequestFor32bitAllocationWithoutPreexistingHostPtrWhe
|
||||
memoryManager.freeGraphicsMemoryImpl(alloc);
|
||||
}
|
||||
|
||||
TEST_F(WddmLinuxTest, whenCheckedIfResourcesCleanupCanBeSkippedAndDeviceIsAliveThenReturnsFalse) {
|
||||
osEnvironment->gdi->getDeviceState = getDeviceStateMock;
|
||||
gdiMockConfig.getDeviceStateClb.returnValue = STATUS_SUCCESS;
|
||||
EXPECT_FALSE(this->wddm->skipResourceCleanup());
|
||||
EXPECT_EQ(1, gdiMockConfig.getDeviceStateClb.callCount);
|
||||
}
|
||||
|
||||
TEST_F(WddmLinuxTest, whenCheckedIfResourcesCleanupCanBeSkippedAndDeviceIsLostThenReturnsTrue) {
|
||||
osEnvironment->gdi->getDeviceState = getDeviceStateMock;
|
||||
gdiMockConfig.getDeviceStateClb.returnValue = -1;
|
||||
EXPECT_TRUE(this->wddm->skipResourceCleanup());
|
||||
EXPECT_EQ(1, gdiMockConfig.getDeviceStateClb.callCount);
|
||||
}
|
||||
|
||||
class MockOsTimeLinux : public NEO::OSTimeLinux {
|
||||
public:
|
||||
MockOsTimeLinux(NEO::OSInterface *osInterface, std::unique_ptr<NEO::DeviceTime> deviceTime) : NEO::OSTimeLinux(osInterface, std::move(deviceTime)) {}
|
||||
|
@ -70,4 +70,9 @@ TEST_F(WddmTests, givenWddmWhenPassesIncorrectHandleToVerifyNTHandleThenReturnFa
|
||||
EXPECT_FALSE(wddm->verifyNTHandle(handle));
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, whenCheckedIfResourcesCleanupCanBeSkippedThenReturnsFalse) {
|
||||
init();
|
||||
EXPECT_FALSE(wddm->skipResourceCleanup());
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
Reference in New Issue
Block a user