mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 14:55:24 +08:00
Ensure that BO handle is closed only once
When one process had exported and then opened IPC handle of memory, then close function was called twice for the same BO handle. It caused debugBreak() and aborted an application. This change allows multiple separate BOs to share one handle. The last shared handle owner calls close() function. Related-To: NEO-7200 Signed-off-by: Wrobel, Patryk <patryk.wrobel@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
272427bb1c
commit
4c58eda90d
@@ -181,6 +181,35 @@ TEST_F(DrmBufferObjectTest, whenPrintBOCreateDestroyResultFlagIsSetAndCloseIsCal
|
||||
EXPECT_EQ(expectedValue, idx);
|
||||
}
|
||||
|
||||
TEST_F(DrmBufferObjectTest, whenPrintBOCreateDestroyResultFlagIsSetAndCloseIsCalledButHandleIsSharedThenDebugInfromationIsPrintedThatCloseIsSkipped) {
|
||||
mock->ioctl_expected.total = 1;
|
||||
DebugManagerStateRestore stateRestore;
|
||||
DebugManager.flags.PrintBOCreateDestroyResult.set(true);
|
||||
|
||||
{
|
||||
MockBufferObjectHandleWrapper sharedBoHandleWrapper = bo->acquireSharedOwnershipOfBoHandle();
|
||||
EXPECT_TRUE(bo->isBoHandleShared());
|
||||
|
||||
testing::internal::CaptureStdout();
|
||||
bool result = bo->close();
|
||||
EXPECT_EQ(true, result);
|
||||
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
size_t idx = output.find("Skipped closing BO-");
|
||||
size_t expectedValue = 0u;
|
||||
EXPECT_EQ(expectedValue, idx);
|
||||
}
|
||||
|
||||
testing::internal::CaptureStdout();
|
||||
bool result = bo->close();
|
||||
EXPECT_EQ(true, result);
|
||||
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
size_t idx = output.find("Calling gem close on handle: BO-");
|
||||
size_t expectedValue = 0;
|
||||
EXPECT_EQ(expectedValue, idx);
|
||||
}
|
||||
|
||||
TEST_F(DrmBufferObjectTest, whenPrintExecutionBufferIsSetToTrueThenMessageFoundInStdStream) {
|
||||
mock->ioctl_expected.total = 1;
|
||||
DebugManagerStateRestore restore;
|
||||
@@ -620,3 +649,140 @@ TEST_F(DrmBufferObjectTest, whenBoRequiresExplicitResidencyThenTheCorrespondingQ
|
||||
EXPECT_EQ(required, bo.isExplicitResidencyRequired());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandleThenControlBlockIsNotCreatedAndInternalHandleIsStored) {
|
||||
constexpr int boHandle{5};
|
||||
MockBufferObjectHandleWrapper boHandleWrapper{boHandle};
|
||||
|
||||
EXPECT_EQ(nullptr, boHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(boHandle, boHandleWrapper.getBoHandle());
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandleWhenAskingIfCanBeClosedThenReturnTrue) {
|
||||
constexpr int boHandle{21};
|
||||
MockBufferObjectHandleWrapper boHandleWrapper{boHandle};
|
||||
|
||||
EXPECT_TRUE(boHandleWrapper.canCloseBoHandle());
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenSettingNewValueThenStoreIt) {
|
||||
constexpr int boHandle{13};
|
||||
MockBufferObjectHandleWrapper boHandleWrapper{boHandle};
|
||||
|
||||
boHandleWrapper.setBoHandle(-1);
|
||||
EXPECT_EQ(-1, boHandleWrapper.getBoHandle());
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandleWhenMakingItSharedThenControlBlockIsCreatedAndReferenceCounterIsValid) {
|
||||
constexpr int boHandle{85};
|
||||
MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle};
|
||||
MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership();
|
||||
|
||||
ASSERT_NE(nullptr, firstBoHandleWrapper.controlBlock);
|
||||
ASSERT_NE(nullptr, secondBoHandleWrapper.controlBlock);
|
||||
|
||||
EXPECT_EQ(firstBoHandleWrapper.controlBlock, secondBoHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(firstBoHandleWrapper.boHandle, secondBoHandleWrapper.boHandle);
|
||||
|
||||
EXPECT_EQ(2, firstBoHandleWrapper.controlBlock->refCount);
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenMoreThanOneSharedHandleWrapperWhenAskingIfHandleCanBeClosedThenReturnFalse) {
|
||||
constexpr int boHandle{121};
|
||||
MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle};
|
||||
MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership();
|
||||
|
||||
EXPECT_FALSE(firstBoHandleWrapper.canCloseBoHandle());
|
||||
EXPECT_FALSE(secondBoHandleWrapper.canCloseBoHandle());
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenOnlyOneReferenceLeftThenHandleCanBeClosed) {
|
||||
constexpr int boHandle{121};
|
||||
MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle};
|
||||
|
||||
{
|
||||
MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership();
|
||||
|
||||
ASSERT_NE(nullptr, firstBoHandleWrapper.controlBlock);
|
||||
ASSERT_NE(nullptr, secondBoHandleWrapper.controlBlock);
|
||||
|
||||
EXPECT_EQ(firstBoHandleWrapper.controlBlock, secondBoHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(2, firstBoHandleWrapper.controlBlock->refCount);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(firstBoHandleWrapper.canCloseBoHandle());
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenOnlyWeakReferencesLeftThenItIsNotDestroyed) {
|
||||
constexpr int boHandle{777};
|
||||
auto firstBoHandleWrapper = std::make_unique<MockBufferObjectHandleWrapper>(boHandle);
|
||||
MockBufferObjectHandleWrapper weakHandleWrapper = firstBoHandleWrapper->acquireWeakOwnership();
|
||||
|
||||
ASSERT_NE(nullptr, firstBoHandleWrapper->controlBlock);
|
||||
ASSERT_NE(nullptr, weakHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(firstBoHandleWrapper->controlBlock, weakHandleWrapper.controlBlock);
|
||||
|
||||
firstBoHandleWrapper.reset();
|
||||
|
||||
EXPECT_EQ(0, weakHandleWrapper.controlBlock->refCount);
|
||||
EXPECT_EQ(1, weakHandleWrapper.controlBlock->weakRefCount);
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenWeakReferencesLeftAndOnlyOneStrongReferenceLeftThenHandleCanBeClosed) {
|
||||
constexpr int boHandle{353};
|
||||
MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle};
|
||||
MockBufferObjectHandleWrapper firstWeakHandleWrapper = firstBoHandleWrapper.acquireWeakOwnership();
|
||||
MockBufferObjectHandleWrapper secondWeakHandleWrapper = firstBoHandleWrapper.acquireWeakOwnership();
|
||||
|
||||
ASSERT_NE(nullptr, firstBoHandleWrapper.controlBlock);
|
||||
ASSERT_NE(nullptr, firstWeakHandleWrapper.controlBlock);
|
||||
ASSERT_NE(nullptr, secondWeakHandleWrapper.controlBlock);
|
||||
|
||||
EXPECT_EQ(firstBoHandleWrapper.controlBlock, firstWeakHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(firstBoHandleWrapper.controlBlock, secondWeakHandleWrapper.controlBlock);
|
||||
|
||||
EXPECT_EQ(1, firstBoHandleWrapper.controlBlock->refCount);
|
||||
EXPECT_EQ(2, firstBoHandleWrapper.controlBlock->weakRefCount);
|
||||
|
||||
EXPECT_TRUE(firstBoHandleWrapper.canCloseBoHandle());
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenConstructingMoreThanTwoSharedResourcesControlBlockRemainsTheSameAndReferenceCounterIsUpdatedOnCreationAndDestruction) {
|
||||
constexpr int boHandle{85};
|
||||
MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle};
|
||||
MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership();
|
||||
|
||||
ASSERT_EQ(firstBoHandleWrapper.controlBlock, secondBoHandleWrapper.controlBlock);
|
||||
|
||||
auto controlBlock = firstBoHandleWrapper.controlBlock;
|
||||
ASSERT_NE(nullptr, controlBlock);
|
||||
EXPECT_EQ(2, controlBlock->refCount);
|
||||
|
||||
{
|
||||
MockBufferObjectHandleWrapper thirdBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership();
|
||||
EXPECT_EQ(firstBoHandleWrapper.boHandle, thirdBoHandleWrapper.boHandle);
|
||||
|
||||
ASSERT_EQ(controlBlock, thirdBoHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(3, controlBlock->refCount);
|
||||
}
|
||||
|
||||
EXPECT_EQ(2, controlBlock->refCount);
|
||||
}
|
||||
|
||||
TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenMoveConstructingAnotherObjectThenInternalDataIsCleared) {
|
||||
constexpr int boHandle{27};
|
||||
MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle};
|
||||
MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership();
|
||||
|
||||
auto oldControlBlock = firstBoHandleWrapper.controlBlock;
|
||||
auto oldBoHandle = firstBoHandleWrapper.boHandle;
|
||||
|
||||
MockBufferObjectHandleWrapper anotherWrapper{std::move(firstBoHandleWrapper)};
|
||||
EXPECT_EQ(oldControlBlock, anotherWrapper.controlBlock);
|
||||
EXPECT_EQ(oldBoHandle, anotherWrapper.boHandle);
|
||||
|
||||
EXPECT_EQ(nullptr, firstBoHandleWrapper.controlBlock);
|
||||
EXPECT_EQ(-1, firstBoHandleWrapper.boHandle);
|
||||
|
||||
EXPECT_EQ(2, secondBoHandleWrapper.controlBlock->refCount);
|
||||
}
|
||||
|
||||
@@ -839,6 +839,66 @@ TEST_F(DrmMemoryManagerTest, GivenAllocationWhenClosingSharedHandleThenSucceeds)
|
||||
memoryManager->freeGraphicsMemory(graphicsAllocation);
|
||||
}
|
||||
|
||||
TEST_F(DrmMemoryManagerTest, GivenNullptrDrmAllocationWhenTryingToRegisterItThenRegisterSharedBoHandleAllocationDoesNothing) {
|
||||
ASSERT_TRUE(memoryManager->sharedBoHandles.empty());
|
||||
|
||||
memoryManager->registerSharedBoHandleAllocation(nullptr);
|
||||
EXPECT_TRUE(memoryManager->sharedBoHandles.empty());
|
||||
}
|
||||
|
||||
TEST_F(DrmMemoryManagerTest, GivenAllocationWhenTryingToRegisterIpcExportedThenItsBoIsMarkedAsSharedHandleAndHandleIsStored) {
|
||||
mock->ioctl_expected.gemUserptr = 1;
|
||||
mock->ioctl_expected.gemWait = 1;
|
||||
mock->ioctl_expected.gemClose = 1;
|
||||
|
||||
ASSERT_TRUE(memoryManager->sharedBoHandles.empty());
|
||||
|
||||
auto alloc = static_cast<DrmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{rootDeviceIndex, MemoryConstants::pageSize}));
|
||||
ASSERT_NE(nullptr, alloc);
|
||||
EXPECT_NE(nullptr, alloc->getBO());
|
||||
|
||||
memoryManager->registerIpcExportedAllocation(alloc);
|
||||
EXPECT_FALSE(memoryManager->sharedBoHandles.empty());
|
||||
|
||||
auto &bos = alloc->getBOs();
|
||||
for (auto *bo : bos) {
|
||||
if (bo) {
|
||||
EXPECT_TRUE(bo->isBoHandleShared());
|
||||
EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(bo->getHandle()));
|
||||
}
|
||||
}
|
||||
|
||||
memoryManager->freeGraphicsMemory(alloc);
|
||||
EXPECT_TRUE(memoryManager->sharedBoHandles.empty());
|
||||
}
|
||||
|
||||
TEST_F(DrmMemoryManagerTest, GivenEmptySharedBoHandlesContainerWhenTryingToGetSharedOwnershipOfNonregisteredHandleThenCreateNewWrapper) {
|
||||
ASSERT_TRUE(memoryManager->sharedBoHandles.empty());
|
||||
|
||||
const int someNonregisteredHandle{123};
|
||||
auto boHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(someNonregisteredHandle);
|
||||
EXPECT_EQ(someNonregisteredHandle, boHandleWrapper.getBoHandle());
|
||||
EXPECT_TRUE(memoryManager->sharedBoHandles.empty());
|
||||
}
|
||||
|
||||
TEST_F(DrmMemoryManagerTest, GivenWrapperInBoHandlesContainerWhenTryingToGetSharedOwnershipOfWrappedHandleThenGetSharedOwnership) {
|
||||
const int boHandle{27};
|
||||
BufferObjectHandleWrapper boHandleWrapper{boHandle};
|
||||
|
||||
memoryManager->sharedBoHandles.emplace(boHandle, boHandleWrapper.acquireWeakOwnership());
|
||||
ASSERT_EQ(1u, memoryManager->sharedBoHandles.count(boHandle));
|
||||
|
||||
{
|
||||
auto newBoHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(boHandle);
|
||||
EXPECT_EQ(boHandle, newBoHandleWrapper.getBoHandle());
|
||||
EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(boHandle));
|
||||
EXPECT_FALSE(newBoHandleWrapper.canCloseBoHandle());
|
||||
}
|
||||
|
||||
EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(boHandle));
|
||||
EXPECT_TRUE(boHandleWrapper.canCloseBoHandle());
|
||||
}
|
||||
|
||||
TEST_F(DrmMemoryManagerTest, GivenDeviceSharedAllocationWhichRequiresHostMapThenCorrectAlignmentReturned) {
|
||||
mock->ioctl_expected.primeFdToHandle = 1;
|
||||
mock->ioctl_expected.gemWait = 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 Intel Corporation
|
||||
* Copyright (C) 2019-2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -34,7 +34,7 @@ TEST(FileLogger, GivenLogAllocationMemoryPoolFlagThenLogsCorrectInfo) {
|
||||
allocation.setCpuPtrAndGpuAddress(&allocation, canonizedGpuAddress);
|
||||
|
||||
MockBufferObject bo(&drm);
|
||||
bo.handle = 4;
|
||||
bo.handle.setBoHandle(4);
|
||||
|
||||
allocation.bufferObjects[0] = &bo;
|
||||
|
||||
@@ -85,7 +85,7 @@ TEST(FileLogger, givenLogAllocationStdoutWhenLogAllocationThenLogToStdoutInstead
|
||||
allocation.setCpuPtrAndGpuAddress(&allocation, canonizedGpuAddress);
|
||||
|
||||
MockBufferObject bo(&drm);
|
||||
bo.handle = 4;
|
||||
bo.handle.setBoHandle(4);
|
||||
|
||||
allocation.bufferObjects[0] = &bo;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user