diff --git a/shared/source/os_interface/linux/drm_buffer_object.cpp b/shared/source/os_interface/linux/drm_buffer_object.cpp index 991636d66c..937dda3738 100644 --- a/shared/source/os_interface/linux/drm_buffer_object.cpp +++ b/shared/source/os_interface/linux/drm_buffer_object.cpp @@ -35,7 +35,7 @@ BufferObjectHandleWrapper BufferObjectHandleWrapper::acquireSharedOwnership() { std::lock_guard lock{controlBlock->blockMutex}; controlBlock->refCount++; - return BufferObjectHandleWrapper{boHandle, Ownership::strong, controlBlock}; + return BufferObjectHandleWrapper{boHandle, rootDeviceIndex, Ownership::strong, controlBlock}; } BufferObjectHandleWrapper BufferObjectHandleWrapper::acquireWeakOwnership() { @@ -46,7 +46,7 @@ BufferObjectHandleWrapper BufferObjectHandleWrapper::acquireWeakOwnership() { std::lock_guard lock{controlBlock->blockMutex}; controlBlock->weakRefCount++; - return BufferObjectHandleWrapper{boHandle, Ownership::weak, controlBlock}; + return BufferObjectHandleWrapper{boHandle, rootDeviceIndex, Ownership::weak, controlBlock}; } BufferObjectHandleWrapper::~BufferObjectHandleWrapper() { @@ -79,7 +79,7 @@ bool BufferObjectHandleWrapper::canCloseBoHandle() { } BufferObject::BufferObject(uint32_t rootDeviceIndex, Drm *drm, uint64_t patIndex, int handle, size_t size, size_t maxOsContextCount) - : BufferObject(rootDeviceIndex, drm, patIndex, BufferObjectHandleWrapper{handle}, size, maxOsContextCount) {} + : BufferObject(rootDeviceIndex, drm, patIndex, BufferObjectHandleWrapper{handle, rootDeviceIndex}, size, maxOsContextCount) {} BufferObject::BufferObject(uint32_t rootDeviceIndex, Drm *drm, uint64_t patIndex, BufferObjectHandleWrapper &&handle, size_t size, size_t maxOsContextCount) : drm(drm), handle(std::move(handle)), size(size), refCount(1), rootDeviceIndex(rootDeviceIndex) { diff --git a/shared/source/os_interface/linux/drm_buffer_object.h b/shared/source/os_interface/linux/drm_buffer_object.h index db1d045e57..30c3dd14e1 100644 --- a/shared/source/os_interface/linux/drm_buffer_object.h +++ b/shared/source/os_interface/linux/drm_buffer_object.h @@ -45,11 +45,11 @@ class BufferObjectHandleWrapper { }; public: - explicit BufferObjectHandleWrapper(int boHandle) noexcept - : boHandle{boHandle} {} + explicit BufferObjectHandleWrapper(int boHandle, uint32_t rootDeviceIndex) noexcept + : boHandle{boHandle}, rootDeviceIndex(rootDeviceIndex) {} BufferObjectHandleWrapper(BufferObjectHandleWrapper &&other) noexcept - : boHandle(std::exchange(other.boHandle, -1)), ownership(other.ownership), controlBlock(std::exchange(other.controlBlock, nullptr)) {} + : boHandle(std::exchange(other.boHandle, -1)), rootDeviceIndex(std::exchange(other.rootDeviceIndex, UINT32_MAX)), ownership(other.ownership), controlBlock(std::exchange(other.controlBlock, nullptr)) {} ~BufferObjectHandleWrapper(); @@ -65,16 +65,23 @@ class BufferObjectHandleWrapper { int getBoHandle() const { return boHandle; } + uint32_t getRootDeviceIndex() const { + return rootDeviceIndex; + } void setBoHandle(int handle) { boHandle = handle; } + void setRootDeviceIndex(uint32_t index) { + rootDeviceIndex = index; + } protected: - BufferObjectHandleWrapper(int boHandle, Ownership ownership, ControlBlock *controlBlock) - : boHandle{boHandle}, ownership{ownership}, controlBlock{controlBlock} {} + BufferObjectHandleWrapper(int boHandle, uint32_t rootDeviceIndex, Ownership ownership, ControlBlock *controlBlock) + : boHandle{boHandle}, rootDeviceIndex{rootDeviceIndex}, ownership{ownership}, controlBlock{controlBlock} {} int boHandle{}; + uint32_t rootDeviceIndex{UINT32_MAX}; Ownership ownership{Ownership::strong}; ControlBlock *controlBlock{nullptr}; }; diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index d083c2bb70..f13760e486 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -239,13 +239,13 @@ uint32_t DrmMemoryManager::unreference(NEO::BufferObject *bo, bool synchronousDe if (bo->peekIsReusableAllocation()) { eraseSharedBufferObject(bo); } - + auto rootDeviceIndex = bo->getRootDeviceIndex(); int boHandle = bo->getHandle(); bo->close(); if (bo->isBoHandleShared() && bo->getHandle() != boHandle) { // Shared BO was closed - handle was invalidated. Remove weak reference from container. - eraseSharedBoHandleWrapper(boHandle); + eraseSharedBoHandleWrapper(boHandle, rootDeviceIndex); } if (lock) { @@ -926,7 +926,7 @@ GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromMultipleShared totalSize += size; auto patIndex = drm.getPatIndex(nullptr, properties.allocationType, CacheRegion::defaultRegion, CachePolicy::writeBack, false, MemoryPoolHelper::isSystemMemoryPool(memoryPool)); - auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle); + auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle, properties.rootDeviceIndex} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle, properties.rootDeviceIndex); bo = new (std::nothrow) BufferObject(properties.rootDeviceIndex, &drm, patIndex, std::move(boHandleWrapper), size, maxOsContextCount); i++; @@ -1007,32 +1007,32 @@ void DrmMemoryManager::registerSharedBoHandleAllocation(DrmAllocation *drmAlloca } auto &bos = drmAllocation->getBOs(); + auto rootDeviceIndex = drmAllocation->getRootDeviceIndex(); for (auto *bo : bos) { if (bo == nullptr) { continue; } - auto foundHandleWrapperIt = sharedBoHandles.find(bo->getHandle()); + auto foundHandleWrapperIt = sharedBoHandles.find(std::pair(bo->getHandle(), rootDeviceIndex)); if (foundHandleWrapperIt == std::end(sharedBoHandles)) { - sharedBoHandles.emplace(bo->getHandle(), bo->acquireWeakOwnershipOfBoHandle()); + sharedBoHandles.emplace(std::make_pair(bo->getHandle(), rootDeviceIndex), bo->acquireWeakOwnershipOfBoHandle()); } else { bo->markAsSharedBoHandle(); } } } -BufferObjectHandleWrapper DrmMemoryManager::tryToGetBoHandleWrapperWithSharedOwnership(int boHandle) { - auto foundHandleWrapperIt = sharedBoHandles.find(boHandle); +BufferObjectHandleWrapper DrmMemoryManager::tryToGetBoHandleWrapperWithSharedOwnership(int boHandle, uint32_t rootDeviceIndex) { + auto foundHandleWrapperIt = sharedBoHandles.find(std::make_pair(boHandle, rootDeviceIndex)); if (foundHandleWrapperIt == std::end(sharedBoHandles)) { - return BufferObjectHandleWrapper{boHandle}; + return BufferObjectHandleWrapper{boHandle, rootDeviceIndex}; } - return foundHandleWrapperIt->second.acquireSharedOwnership(); } -void DrmMemoryManager::eraseSharedBoHandleWrapper(int boHandle) { - auto foundHandleWrapperIt = sharedBoHandles.find(boHandle); +void DrmMemoryManager::eraseSharedBoHandleWrapper(int boHandle, uint32_t rootDeviceIndex) { + auto foundHandleWrapperIt = sharedBoHandles.find(std::make_pair(boHandle, rootDeviceIndex)); if (foundHandleWrapperIt != std::end(sharedBoHandles)) { sharedBoHandles.erase(foundHandleWrapperIt); } @@ -1079,7 +1079,7 @@ GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromSharedHandle(c UNRECOVERABLE_IF(size == std::numeric_limits::max()); auto patIndex = drm.getPatIndex(nullptr, properties.allocationType, CacheRegion::defaultRegion, CachePolicy::writeBack, false, MemoryPoolHelper::isSystemMemoryPool(memoryPool)); - auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle); + auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle, properties.rootDeviceIndex} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle, properties.rootDeviceIndex); bo = new (std::nothrow) BufferObject(properties.rootDeviceIndex, &drm, patIndex, std::move(boHandleWrapper), size, maxOsContextCount); @@ -2633,7 +2633,7 @@ DrmAllocation *DrmMemoryManager::createUSMHostAllocationFromSharedHandle(osHandl } auto boHandle = static_cast(openFd.handle); - auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle); + auto boHandleWrapper = reuseSharedAllocation ? BufferObjectHandleWrapper{boHandle, properties.rootDeviceIndex} : tryToGetBoHandleWrapperWithSharedOwnership(boHandle, properties.rootDeviceIndex); const bool useBooMmap = drm.getMemoryInfo() && properties.useMmapObject; if (!useBooMmap) { diff --git a/shared/source/os_interface/linux/drm_memory_manager.h b/shared/source/os_interface/linux/drm_memory_manager.h index 84ba4a1461..2d9c2935e7 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.h +++ b/shared/source/os_interface/linux/drm_memory_manager.h @@ -24,6 +24,12 @@ enum class AtomicAccessMode : uint32_t; enum class GemCloseWorkerMode; +struct BoHandleDeviceIndexPairComparer { + bool operator()(std::pair const &lhs, std::pair const &rhs) const { + return (lhs.first < rhs.first) || (lhs.second < rhs.second); + } +}; + class DrmMemoryManager : public MemoryManager { public: DrmMemoryManager(GemCloseWorkerMode mode, @@ -114,8 +120,8 @@ class DrmMemoryManager : public MemoryManager { protected: void registerSharedBoHandleAllocation(DrmAllocation *drmAllocation); - BufferObjectHandleWrapper tryToGetBoHandleWrapperWithSharedOwnership(int boHandle); - void eraseSharedBoHandleWrapper(int boHandle); + BufferObjectHandleWrapper tryToGetBoHandleWrapperWithSharedOwnership(int boHandle, uint32_t rootDeviceIndex); + void eraseSharedBoHandleWrapper(int boHandle, uint32_t rootDeviceIndex); MOCKABLE_VIRTUAL BufferObject *findAndReferenceSharedBufferObject(int boHandle, uint32_t rootDeviceIndex); void eraseSharedBufferObject(BufferObject *bo); @@ -187,7 +193,7 @@ class DrmMemoryManager : public MemoryManager { std::vector sharingBufferObjects; std::mutex mtx; - std::map sharedBoHandles; + std::map, BufferObjectHandleWrapper, BoHandleDeviceIndexPairComparer> sharedBoHandles; std::vector> localMemAllocs; std::vector localMemBanksCount; std::vector sysMemAllocs; diff --git a/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp index ded89f1e1b..ecda22c8ba 100644 --- a/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp @@ -1002,30 +1002,33 @@ TEST_F(DrmBufferObjectTest, whenBoRequiresExplicitResidencyThenTheCorrespondingQ TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandleThenControlBlockIsNotCreatedAndInternalHandleIsStored) { constexpr int boHandle{5}; - MockBufferObjectHandleWrapper boHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper boHandleWrapper{boHandle, 1u}; EXPECT_EQ(nullptr, boHandleWrapper.controlBlock); EXPECT_EQ(boHandle, boHandleWrapper.getBoHandle()); + EXPECT_EQ(1u, boHandleWrapper.getRootDeviceIndex()); } TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandleWhenAskingIfCanBeClosedThenReturnTrue) { constexpr int boHandle{21}; - MockBufferObjectHandleWrapper boHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper boHandleWrapper{boHandle, 1u}; EXPECT_TRUE(boHandleWrapper.canCloseBoHandle()); } TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenSettingNewValueThenStoreIt) { constexpr int boHandle{13}; - MockBufferObjectHandleWrapper boHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper boHandleWrapper{boHandle, 1u}; boHandleWrapper.setBoHandle(-1); + boHandleWrapper.setRootDeviceIndex(4u); EXPECT_EQ(-1, boHandleWrapper.getBoHandle()); + EXPECT_EQ(4u, boHandleWrapper.getRootDeviceIndex()); } TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandleWhenMakingItSharedThenControlBlockIsCreatedAndReferenceCounterIsValid) { constexpr int boHandle{85}; - MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle, 1u}; MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership(); ASSERT_NE(nullptr, firstBoHandleWrapper.controlBlock); @@ -1039,7 +1042,7 @@ TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperConstructedFromNonSharedHandl TEST(DrmBufferObjectHandleWrapperTest, GivenMoreThanOneSharedHandleWrapperWhenAskingIfHandleCanBeClosedThenReturnFalse) { constexpr int boHandle{121}; - MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle, 1u}; MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership(); EXPECT_FALSE(firstBoHandleWrapper.canCloseBoHandle()); @@ -1048,7 +1051,7 @@ TEST(DrmBufferObjectHandleWrapperTest, GivenMoreThanOneSharedHandleWrapperWhenAs TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenOnlyOneReferenceLeftThenHandleCanBeClosed) { constexpr int boHandle{121}; - MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle, 1u}; { MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership(); @@ -1065,7 +1068,7 @@ TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenOnlyOneRefere TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenOnlyWeakReferencesLeftThenItIsNotDestroyed) { constexpr int boHandle{777}; - auto firstBoHandleWrapper = std::make_unique(boHandle); + auto firstBoHandleWrapper = std::make_unique(boHandle, 1u); MockBufferObjectHandleWrapper weakHandleWrapper = firstBoHandleWrapper->acquireWeakOwnership(); ASSERT_NE(nullptr, firstBoHandleWrapper->controlBlock); @@ -1080,7 +1083,7 @@ TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenOnlyWeakRefer TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenWeakReferencesLeftAndOnlyOneStrongReferenceLeftThenHandleCanBeClosed) { constexpr int boHandle{353}; - MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle, 1u}; MockBufferObjectHandleWrapper firstWeakHandleWrapper = firstBoHandleWrapper.acquireWeakOwnership(); MockBufferObjectHandleWrapper secondWeakHandleWrapper = firstBoHandleWrapper.acquireWeakOwnership(); @@ -1099,7 +1102,7 @@ TEST(DrmBufferObjectHandleWrapperTest, GivenControlBlockCreatedWhenWeakReference TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenConstructingMoreThanTwoSharedResourcesControlBlockRemainsTheSameAndReferenceCounterIsUpdatedOnCreationAndDestruction) { constexpr int boHandle{85}; - MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle, 1u}; MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership(); ASSERT_EQ(firstBoHandleWrapper.controlBlock, secondBoHandleWrapper.controlBlock); @@ -1121,7 +1124,7 @@ TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenConstructingMoreThanTwoSh TEST(DrmBufferObjectHandleWrapperTest, GivenWrapperWhenMoveConstructingAnotherObjectThenInternalDataIsCleared) { constexpr int boHandle{27}; - MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle}; + MockBufferObjectHandleWrapper firstBoHandleWrapper{boHandle, 1u}; MockBufferObjectHandleWrapper secondBoHandleWrapper = firstBoHandleWrapper.acquireSharedOwnership(); auto oldControlBlock = firstBoHandleWrapper.controlBlock; @@ -1186,4 +1189,4 @@ TEST_F(DrmBufferObjectTest, givenBufferObjectWhenSetIsLockableIsCalledThenIsLock bo.setIsLockable(isLockable); EXPECT_EQ(isLockable, bo.isLockable()); } -} \ No newline at end of file +} diff --git a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp index 530ca8df41..2b919f23b3 100644 --- a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp @@ -1098,7 +1098,7 @@ TEST_F(DrmMemoryManagerTest, GivenAllocationWhenTryingToRegisterIpcExportedThenI for (auto *bo : bos) { if (bo) { EXPECT_TRUE(bo->isBoHandleShared()); - EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(bo->getHandle())); + EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(bo->getHandle(), rootDeviceIndex))); } } @@ -1110,26 +1110,64 @@ TEST_F(DrmMemoryManagerTest, GivenEmptySharedBoHandlesContainerWhenTryingToGetSh ASSERT_TRUE(memoryManager->sharedBoHandles.empty()); const int someNonregisteredHandle{123}; - auto boHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(someNonregisteredHandle); + auto boHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(someNonregisteredHandle, rootDeviceIndex); EXPECT_EQ(someNonregisteredHandle, boHandleWrapper.getBoHandle()); EXPECT_TRUE(memoryManager->sharedBoHandles.empty()); } TEST_F(DrmMemoryManagerTest, GivenWrapperInBoHandlesContainerWhenTryingToGetSharedOwnershipOfWrappedHandleThenGetSharedOwnership) { const int boHandle{27}; - BufferObjectHandleWrapper boHandleWrapper{boHandle}; + BufferObjectHandleWrapper boHandleWrapper{boHandle, rootDeviceIndex}; - memoryManager->sharedBoHandles.emplace(boHandle, boHandleWrapper.acquireWeakOwnership()); - ASSERT_EQ(1u, memoryManager->sharedBoHandles.count(boHandle)); + memoryManager->sharedBoHandles.emplace(std::make_pair(boHandle, rootDeviceIndex), boHandleWrapper.acquireWeakOwnership()); + ASSERT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); { - auto newBoHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(boHandle); + auto newBoHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(boHandle, rootDeviceIndex); EXPECT_EQ(boHandle, newBoHandleWrapper.getBoHandle()); - EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(boHandle)); + EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); EXPECT_FALSE(newBoHandleWrapper.canCloseBoHandle()); } - EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(boHandle)); + EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); + EXPECT_TRUE(boHandleWrapper.canCloseBoHandle()); +} + +TEST_F(DrmMemoryManagerTest, GivenWrapperInBoHandlesContainerWhenTryingToGetSharedOwnershipOfWrappedHandleWithDifferentDeviceIndexThenGetNonSharedOwnership) { + const int boHandle{27}; + BufferObjectHandleWrapper boHandleWrapper{boHandle, rootDeviceIndex}; + + memoryManager->sharedBoHandles.emplace(std::make_pair(boHandle, rootDeviceIndex), boHandleWrapper.acquireWeakOwnership()); + ASSERT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); + + { + auto newBoHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(boHandle, rootDeviceIndex + 1); + EXPECT_EQ(boHandle, newBoHandleWrapper.getBoHandle()); + EXPECT_NE(rootDeviceIndex, newBoHandleWrapper.getRootDeviceIndex()); + EXPECT_EQ(0u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex + 1))); + EXPECT_TRUE(newBoHandleWrapper.canCloseBoHandle()); + } + + EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); + EXPECT_TRUE(boHandleWrapper.canCloseBoHandle()); +} + +TEST_F(DrmMemoryManagerTest, GivenWrapperInBoHandlesContainerWhenTryingToGetSharedOwnershipOfWrappedHandleWithDifferentHandleIndexPairThenGetNonSharedOwnership) { + const int boHandle{27}; + BufferObjectHandleWrapper boHandleWrapper{boHandle, rootDeviceIndex}; + + memoryManager->sharedBoHandles.emplace(std::make_pair(boHandle, rootDeviceIndex), boHandleWrapper.acquireWeakOwnership()); + ASSERT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); + + { + auto newBoHandleWrapper = memoryManager->tryToGetBoHandleWrapperWithSharedOwnership(boHandle + 1, rootDeviceIndex + 1); + EXPECT_NE(boHandle, newBoHandleWrapper.getBoHandle()); + EXPECT_NE(rootDeviceIndex, newBoHandleWrapper.getRootDeviceIndex()); + EXPECT_EQ(0u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle + 1, rootDeviceIndex + 1))); + EXPECT_TRUE(newBoHandleWrapper.canCloseBoHandle()); + } + + EXPECT_EQ(1u, memoryManager->sharedBoHandles.count(std::make_pair(boHandle, rootDeviceIndex))); EXPECT_TRUE(boHandleWrapper.canCloseBoHandle()); } @@ -3992,7 +4030,7 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, EXPECT_NE(bo1, nullptr); EXPECT_EQ(static_cast(bo1->getHandle()), mock->outputHandle); EXPECT_FALSE(bo1->isBoHandleShared()); - auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle); + auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); EXPECT_EQ(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles)); memoryManager->freeGraphicsMemory(gfxAllocation1); @@ -4019,7 +4057,7 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, EXPECT_NE(bo1, nullptr); EXPECT_EQ(static_cast(bo1->getHandle()), mock->outputHandle); EXPECT_FALSE(bo1->isBoHandleShared()); - auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle); + auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); EXPECT_EQ(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles)); memoryManager->freeGraphicsMemory(gfxAllocation1); @@ -4046,7 +4084,7 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, EXPECT_NE(bo1, nullptr); EXPECT_EQ(static_cast(bo1->getHandle()), mock->outputHandle); EXPECT_TRUE(bo1->isBoHandleShared()); - auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle); + auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); EXPECT_NE(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles)); EXPECT_TRUE(boHandleWrapperIt1->second.canCloseBoHandle()); @@ -4059,7 +4097,7 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, EXPECT_NE(bo2, nullptr); EXPECT_EQ(static_cast(bo2->getHandle()), mock->outputHandle); EXPECT_TRUE(bo2->isBoHandleShared()); - auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(mock->outputHandle); + auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); EXPECT_EQ(boHandleWrapperIt2, boHandleWrapperIt1); EXPECT_FALSE(boHandleWrapperIt2->second.canCloseBoHandle()); @@ -4069,6 +4107,59 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, memoryManager->freeGraphicsMemory(gfxAllocation1); } +TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, + givenIPCBoHandleAndSharedAllocationReuseDisabledWhenMultipleAllocationsCreatedFromDifferentDevicesThenBoHandlesAreClosedSeparately) { + const bool reuseSharedAllocation = false; + + 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, {}); + + TestedDrmMemoryManager::OsHandleData osHandleData1{11u}; + auto gfxAllocation1 = memoryManager->createGraphicsAllocationFromSharedHandle(&osHandleData1, properties, false, isHostIpcAllocation, reuseSharedAllocation, nullptr); + DrmAllocation *drmAllocation1 = static_cast(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(bo1->getHandle()), mock->outputHandle); + EXPECT_TRUE(bo1->isBoHandleShared()); + auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); + EXPECT_NE(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles)); + EXPECT_TRUE(boHandleWrapperIt1->second.canCloseBoHandle()); + + TestedDrmMemoryManager::OsHandleData osHandleData2{12u}; + // two devices in the system, rootDeviceIndex is set to 1, so set rootDeviceInext to 0 + auto rootDeviceIndex2 = 0; + auto rootDeviceEnvironment2 = executionEnvironment->rootDeviceEnvironments[rootDeviceIndex2].get(); + auto mock2 = static_cast(rootDeviceEnvironment2->osInterface->getDriverModel()->as()); + mock2->ioctlExpected.primeFdToHandle = 1; + mock2->ioctlExpected.gemWait = 1; + mock2->ioctlExpected.gemClose = 1; + mock2->outputHandle = 88u; + AllocationProperties properties2(rootDeviceIndex2, false, 4096u, AllocationType::sharedBuffer, false, {}); + auto gfxAllocation2 = memoryManager->createGraphicsAllocationFromSharedHandle(&osHandleData2, properties2, false, isHostIpcAllocation, false, nullptr); + DrmAllocation *drmAllocation2 = static_cast(gfxAllocation2); + ASSERT_NE(nullptr, drmAllocation2); + // BoHandle registered as shared with WEAK ownership because it's from different root devices - GEM_CLOSE can be called on it + auto bo2 = drmAllocation2->getBO(); + EXPECT_NE(bo2, nullptr); + EXPECT_EQ(static_cast(bo2->getHandle()), mock->outputHandle); + EXPECT_TRUE(bo2->isBoHandleShared()); + auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex2)); + EXPECT_NE(boHandleWrapperIt2, boHandleWrapperIt1); + EXPECT_TRUE(boHandleWrapperIt2->second.canCloseBoHandle()); + + memoryManager->freeGraphicsMemory(gfxAllocation2); + memoryManager->freeGraphicsMemory(gfxAllocation1); + mock2->testIoctls(); + mock2->reset(); +} + TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, givenIPCBoHandleAndSharedAllocationReuseDisabledWhenMultipleAllocationsCreatedFromMultipleSharedHandlesFromSingleProcessThenBoHandleIsClosedOnlyOnce) { const bool reuseSharedAllocation = false; @@ -4090,7 +4181,7 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, EXPECT_NE(bo1, nullptr); EXPECT_EQ(static_cast(bo1->getHandle()), mock->outputHandle); EXPECT_TRUE(bo1->isBoHandleShared()); - auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(mock->outputHandle); + auto boHandleWrapperIt1 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); EXPECT_NE(boHandleWrapperIt1, std::end(memoryManager->sharedBoHandles)); EXPECT_TRUE(boHandleWrapperIt1->second.canCloseBoHandle()); @@ -4103,7 +4194,7 @@ TEST_P(DrmMemoryManagerWithHostIpcAllocationParamTest, EXPECT_NE(bo2, nullptr); EXPECT_EQ(static_cast(bo2->getHandle()), mock->outputHandle); EXPECT_TRUE(bo2->isBoHandleShared()); - auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(mock->outputHandle); + auto boHandleWrapperIt2 = memoryManager->sharedBoHandles.find(std::make_pair(mock->outputHandle, rootDeviceIndex)); EXPECT_EQ(boHandleWrapperIt2, boHandleWrapperIt1); EXPECT_FALSE(boHandleWrapperIt2->second.canCloseBoHandle());