mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-30 01:35:20 +08:00
fix: support zeEventPool IPC handles from single process
For all execution paths where needed, use `BufferObjectHandleWrapper` instances for registration of BO-handles and try to obtain shared ownership. This allows both sides of IPC communication to be implemented in the same process and avoid the double-free problem on a BufferObject of the same handle. Currently there are two pairs of such calls: * `zeEventPoolGetIpcHandle()` + `zeEventPoolOpenIpcHandle()` * `zeMemGetIpcHandle()` + `zeMemOpenIpcHandle()` The capability of executing both sides from the same process is useful for testing but not only. Related-To: NEO-9837 Signed-off-by: Maciej Bielski <maciej.bielski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
b5f698e0c5
commit
134c718a25
@@ -2470,18 +2470,30 @@ DrmAllocation *DrmMemoryManager::createUSMHostAllocationFromSharedHandle(osHandl
|
||||
return allocation;
|
||||
}
|
||||
|
||||
auto boHandle = static_cast<int>(openFd.handle);
|
||||
auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle);
|
||||
|
||||
const bool useBooMmap = drm.getMemoryInfo() && properties.useMmapObject;
|
||||
if (!useBooMmap) {
|
||||
auto bo = new BufferObject(properties.rootDeviceIndex, &drm, patIndex, openFd.handle, properties.size, maxOsContextCount);
|
||||
auto bo = new BufferObject(properties.rootDeviceIndex, &drm, patIndex, std::move(boHandleWrapper), properties.size, maxOsContextCount);
|
||||
bo->setAddress(properties.gpuAddress);
|
||||
|
||||
auto gmmHelper = getGmmHelper(properties.rootDeviceIndex);
|
||||
auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(reinterpret_cast<void *>(bo->peekAddress())));
|
||||
return new DrmAllocation(properties.rootDeviceIndex, properties.allocationType, bo, reinterpret_cast<void *>(bo->peekAddress()), bo->peekSize(),
|
||||
handle, memoryPool, canonizedGpuAddress);
|
||||
auto drmAllocation = std::make_unique<DrmAllocation>(properties.rootDeviceIndex,
|
||||
properties.allocationType,
|
||||
bo,
|
||||
reinterpret_cast<void *>(bo->peekAddress()),
|
||||
bo->peekSize(),
|
||||
handle,
|
||||
memoryPool,
|
||||
canonizedGpuAddress);
|
||||
if (!reuseSharedAllocation) {
|
||||
registerSharedBoHandleAllocation(drmAllocation.get());
|
||||
}
|
||||
return drmAllocation.release();
|
||||
}
|
||||
|
||||
auto boHandle = openFd.handle;
|
||||
BufferObject *bo = nullptr;
|
||||
if (reuseSharedAllocation) {
|
||||
bo = findAndReferenceSharedBufferObject(boHandle, properties.rootDeviceIndex);
|
||||
@@ -2494,7 +2506,7 @@ DrmAllocation *DrmMemoryManager::createUSMHostAllocationFromSharedHandle(osHandl
|
||||
|
||||
memoryPool = MemoryPool::system4KBPages;
|
||||
patIndex = drm.getPatIndex(nullptr, properties.allocationType, CacheRegion::defaultRegion, CachePolicy::writeBack, false, MemoryPoolHelper::isSystemMemoryPool(memoryPool));
|
||||
bo = new BufferObject(properties.rootDeviceIndex, &drm, patIndex, boHandle, size, maxOsContextCount);
|
||||
bo = new BufferObject(properties.rootDeviceIndex, &drm, patIndex, std::move(boHandleWrapper), size, maxOsContextCount);
|
||||
|
||||
if (properties.allocationType == AllocationType::gpuTimestampDeviceBuffer) {
|
||||
cpuPointer = this->mmapFunction(0, size + MemoryConstants::pageSize64k, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
@@ -2553,6 +2565,9 @@ DrmAllocation *DrmMemoryManager::createUSMHostAllocationFromSharedHandle(osHandl
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!reuseSharedAllocation) {
|
||||
registerSharedBoHandleAllocation(drmAllocation.get());
|
||||
}
|
||||
return drmAllocation.release();
|
||||
}
|
||||
|
||||
|
||||
@@ -3858,6 +3858,161 @@ TEST(DrmMemoryManagerFreeGraphicsMemoryUnreferenceTest,
|
||||
EXPECT_EQ(expectedOutput.str(), output);
|
||||
}
|
||||
|
||||
struct DrmMemoryManagerWithHostIpcAllocationParamTest : public DrmMemoryManagerFixture, ::testing::TestWithParam<bool> {
|
||||
void SetUp() override {
|
||||
DrmMemoryManagerFixture::setUp();
|
||||
}
|
||||
void TearDown() override {
|
||||
DrmMemoryManagerFixture::tearDown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest,
|
||||
givenIPCBoHandleAndSharedAllocationReuseEnabledWhenAllocationCreatedThenBoHandleSharingIsNotUsed) {
|
||||
const bool reuseSharedAllocation = true;
|
||||
|
||||
mock->ioctlExpected.primeFdToHandle = 1;
|
||||
mock->ioctlExpected.gemWait = 1;
|
||||
mock->ioctlExpected.gemClose = 1;
|
||||
mock->outputHandle = 88u;
|
||||
bool isHostIpcAllocation = GetParam();
|
||||
AllocationProperties properties(rootDeviceIndex, false, 4096u, AllocationType::sharedBuffer, false, {});
|
||||
|
||||
osHandle handle1 = 11u;
|
||||
auto gfxAllocation1 = memoryManager->createGraphicsAllocationFromSharedHandle(handle1, properties, false, isHostIpcAllocation, reuseSharedAllocation, nullptr);
|
||||
DrmAllocation *drmAllocation1 = static_cast<DrmAllocation *>(gfxAllocation1);
|
||||
ASSERT_NE(nullptr, drmAllocation1);
|
||||
|
||||
// BoHandle not registered as shared at all
|
||||
auto bo1 = drmAllocation1->getBO();
|
||||
EXPECT_NE(bo1, nullptr);
|
||||
EXPECT_EQ(static_cast<uint32_t>(bo1->getHandle()), mock->outputHandle);
|
||||
EXPECT_FALSE(bo1->isBoHandleShared());
|
||||
auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle);
|
||||
EXPECT_EQ(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles));
|
||||
|
||||
memoryManager->freeGraphicsMemory(gfxAllocation1);
|
||||
}
|
||||
|
||||
TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest,
|
||||
givenIPCBoHandleAndSharedAllocationReuseEnabledWhenAllocationCreatedFromMultipleHandlesThenBoHandleSharingIsNotUsed) {
|
||||
const bool reuseSharedAllocation = true;
|
||||
|
||||
mock->ioctlExpected.primeFdToHandle = 1;
|
||||
mock->ioctlExpected.gemWait = 1;
|
||||
mock->ioctlExpected.gemClose = 1;
|
||||
mock->outputHandle = 88u;
|
||||
bool isHostIpcAllocation = GetParam();
|
||||
AllocationProperties properties(rootDeviceIndex, true, 4096u, AllocationType::sharedBuffer, false, {0b0010});
|
||||
|
||||
std::vector<osHandle> handles = {11u};
|
||||
auto gfxAllocation1 = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles, properties, false, isHostIpcAllocation, reuseSharedAllocation, nullptr);
|
||||
DrmAllocation *drmAllocation1 = static_cast<DrmAllocation *>(gfxAllocation1);
|
||||
ASSERT_NE(nullptr, drmAllocation1);
|
||||
|
||||
// BoHandle not registered as shared at all
|
||||
auto bo1 = drmAllocation1->getBO();
|
||||
EXPECT_NE(bo1, nullptr);
|
||||
EXPECT_EQ(static_cast<uint32_t>(bo1->getHandle()), mock->outputHandle);
|
||||
EXPECT_FALSE(bo1->isBoHandleShared());
|
||||
auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle);
|
||||
EXPECT_EQ(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles));
|
||||
|
||||
memoryManager->freeGraphicsMemory(gfxAllocation1);
|
||||
}
|
||||
|
||||
TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest,
|
||||
givenIPCBoHandleAndSharedAllocationReuseDisabledWhenMultipleAllocationsCreatedFromSingleProcessThenBoHandleIsClosedOnlyOnce) {
|
||||
const bool reuseSharedAllocation = false;
|
||||
|
||||
mock->ioctlExpected.primeFdToHandle = 2;
|
||||
mock->ioctlExpected.gemWait = 2;
|
||||
mock->ioctlExpected.gemClose = 1;
|
||||
mock->outputHandle = 88u;
|
||||
bool isHostIpcAllocation = GetParam();
|
||||
AllocationProperties properties(rootDeviceIndex, false, 4096u, AllocationType::sharedBuffer, false, {});
|
||||
|
||||
osHandle handle1 = 11u;
|
||||
auto gfxAllocation1 = memoryManager->createGraphicsAllocationFromSharedHandle(handle1, properties, false, isHostIpcAllocation, reuseSharedAllocation, nullptr);
|
||||
DrmAllocation *drmAllocation1 = static_cast<DrmAllocation *>(gfxAllocation1);
|
||||
ASSERT_NE(nullptr, drmAllocation1);
|
||||
|
||||
// BoHandle registered as shared but with WEAK ownership - GEM_CLOSE can be called on it
|
||||
auto bo1 = drmAllocation1->getBO();
|
||||
EXPECT_NE(bo1, nullptr);
|
||||
EXPECT_EQ(static_cast<uint32_t>(bo1->getHandle()), mock->outputHandle);
|
||||
EXPECT_TRUE(bo1->isBoHandleShared());
|
||||
auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle);
|
||||
EXPECT_NE(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles));
|
||||
EXPECT_TRUE(boHandleWrapperIt1->second.canCloseBoHandle());
|
||||
|
||||
osHandle handle2 = 12u;
|
||||
auto gfxAllocation2 = memoryManager->createGraphicsAllocationFromSharedHandle(handle2, properties, false, isHostIpcAllocation, false, nullptr);
|
||||
DrmAllocation *drmAllocation2 = static_cast<DrmAllocation *>(gfxAllocation2);
|
||||
ASSERT_NE(nullptr, drmAllocation2);
|
||||
// BoHandle registered as shared with SHARED ownership - GEM_CLOSE cannot be called on it
|
||||
auto bo2 = drmAllocation2->getBO();
|
||||
EXPECT_NE(bo2, nullptr);
|
||||
EXPECT_EQ(static_cast<uint32_t>(bo2->getHandle()), mock->outputHandle);
|
||||
EXPECT_TRUE(bo2->isBoHandleShared());
|
||||
auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(mock->outputHandle);
|
||||
EXPECT_EQ(boHandleWrapperIt2, boHandleWrapperIt1);
|
||||
EXPECT_FALSE(boHandleWrapperIt2->second.canCloseBoHandle());
|
||||
|
||||
memoryManager->freeGraphicsMemory(gfxAllocation2);
|
||||
// GEM_CLOSE can be called on BoHandle again
|
||||
EXPECT_TRUE(boHandleWrapperIt2->second.canCloseBoHandle());
|
||||
memoryManager->freeGraphicsMemory(gfxAllocation1);
|
||||
}
|
||||
|
||||
TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest,
|
||||
givenIPCBoHandleAndSharedAllocationReuseDisabledWhenMultipleAllocationsCreatedFromMultipleSharedHandlesFromSingleProcessThenBoHandleIsClosedOnlyOnce) {
|
||||
const bool reuseSharedAllocation = false;
|
||||
|
||||
mock->ioctlExpected.primeFdToHandle = 2;
|
||||
mock->ioctlExpected.gemWait = 2;
|
||||
mock->ioctlExpected.gemClose = 1;
|
||||
mock->outputHandle = 88u;
|
||||
bool isHostIpcAllocation = GetParam();
|
||||
AllocationProperties properties(rootDeviceIndex, true, 4096u, AllocationType::sharedBuffer, false, {});
|
||||
|
||||
std::vector<osHandle> handles1 = {11u};
|
||||
auto gfxAllocation1 = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles1, properties, false, isHostIpcAllocation, reuseSharedAllocation, nullptr);
|
||||
DrmAllocation *drmAllocation1 = static_cast<DrmAllocation *>(gfxAllocation1);
|
||||
ASSERT_NE(nullptr, drmAllocation1);
|
||||
|
||||
// BoHandle registered as shared but with WEAK ownership - GEM_CLOSE can be called on it
|
||||
auto bo1 = drmAllocation1->getBO();
|
||||
EXPECT_NE(bo1, nullptr);
|
||||
EXPECT_EQ(static_cast<uint32_t>(bo1->getHandle()), mock->outputHandle);
|
||||
EXPECT_TRUE(bo1->isBoHandleShared());
|
||||
auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle);
|
||||
EXPECT_NE(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles));
|
||||
EXPECT_TRUE(boHandleWrapperIt1->second.canCloseBoHandle());
|
||||
|
||||
std::vector<osHandle> handles2 = {12u};
|
||||
auto gfxAllocation2 = memoryManager->createGraphicsAllocationFromMultipleSharedHandles(handles2, properties, false, isHostIpcAllocation, false, nullptr);
|
||||
DrmAllocation *drmAllocation2 = static_cast<DrmAllocation *>(gfxAllocation2);
|
||||
ASSERT_NE(nullptr, drmAllocation2);
|
||||
// BoHandle registered as shared with SHARED ownership - GEM_CLOSE cannot be called on it
|
||||
auto bo2 = drmAllocation2->getBO();
|
||||
EXPECT_NE(bo2, nullptr);
|
||||
EXPECT_EQ(static_cast<uint32_t>(bo2->getHandle()), mock->outputHandle);
|
||||
EXPECT_TRUE(bo2->isBoHandleShared());
|
||||
auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(mock->outputHandle);
|
||||
EXPECT_EQ(boHandleWrapperIt2, boHandleWrapperIt1);
|
||||
EXPECT_FALSE(boHandleWrapperIt2->second.canCloseBoHandle());
|
||||
|
||||
memoryManager->freeGraphicsMemory(gfxAllocation2);
|
||||
// GEM_CLOSE can be called on BoHandle again
|
||||
EXPECT_TRUE(boHandleWrapperIt2->second.canCloseBoHandle());
|
||||
memoryManager->freeGraphicsMemory(gfxAllocation1);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(HostIpcAllocationFlag,
|
||||
DrmMemoryManagerWithHostIpcAllocationParamTest,
|
||||
::testing::Values(false, true));
|
||||
|
||||
TEST(DrmMemoryManagerFreeGraphicsMemoryUnreferenceTest,
|
||||
givenCallToCreateSharedAllocationWithReuseSharedAllocationThenAllocationsSuccedAndAddressesAreTheSame) {
|
||||
MockExecutionEnvironment executionEnvironment(defaultHwInfo.get());
|
||||
|
||||
Reference in New Issue
Block a user