diff --git a/level_zero/core/source/context/context_imp.cpp b/level_zero/core/source/context/context_imp.cpp index e9e126df44..9f6f7dabb8 100644 --- a/level_zero/core/source/context/context_imp.cpp +++ b/level_zero/core/source/context/context_imp.cpp @@ -403,22 +403,25 @@ ze_result_t ContextImp::freeMem(const void *ptr, bool blocking) { return ZE_RESULT_ERROR_INVALID_ARGUMENT; } - for (auto pairDevice : this->devices) { - this->freePeerAllocations(ptr, blocking, Device::fromHandle(pairDevice.second)); - } - this->driverHandle->svmAllocsManager->freeSVMAlloc(const_cast(ptr), blocking); - std::map::iterator ipcHandleIterator; auto lockIPC = this->lockIPCHandleMap(); ipcHandleIterator = this->getIPCHandleMap().begin(); while (ipcHandleIterator != this->getIPCHandleMap().end()) { if (ipcHandleIterator->second->ptr == reinterpret_cast(ptr)) { + auto *memoryManager = driverHandle->getMemoryManager(); + memoryManager->closeInternalHandle(ipcHandleIterator->second->ipcData.handle, ipcHandleIterator->second->handleId, nullptr); delete ipcHandleIterator->second; this->getIPCHandleMap().erase(ipcHandleIterator->first); break; } ipcHandleIterator++; } + + for (auto pairDevice : this->devices) { + this->freePeerAllocations(ptr, blocking, Device::fromHandle(pairDevice.second)); + } + this->driverHandle->svmAllocsManager->freeSVMAlloc(const_cast(ptr), blocking); + return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp b/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp index 8c5f019813..ef988be5be 100644 --- a/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp +++ b/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp @@ -72,6 +72,29 @@ TEST_F(MemoryIPCTests, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryIPCTests, + givenCallToGetIpcHandleWithDeviceAllocationAndCallToMemFreeThenIPCHandleIsClosed) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + ze_ipc_mem_handle_t ipcHandle; + result = context->getIpcMemHandle(ptr, &ipcHandle); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(0u, context->getIPCHandleMap().size()); +} + TEST_F(MemoryIPCTests, givenCallToGetIpcHandleWithDeviceAllocationAndCallToGetFdFromIpcHandleThenIPCHandleReturned) { size_t size = 10; diff --git a/level_zero/core/test/unit_tests/sources/memory/test_memory_wddm.cpp b/level_zero/core/test/unit_tests/sources/memory/test_memory_wddm.cpp index e040734091..7dd636c1f9 100644 --- a/level_zero/core/test/unit_tests/sources/memory/test_memory_wddm.cpp +++ b/level_zero/core/test/unit_tests/sources/memory/test_memory_wddm.cpp @@ -72,6 +72,29 @@ TEST_F(MemoryIPCTests, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryIPCTests, + givenCallToGetIpcHandleWithDeviceAllocationAndCallToMemFreeThenIPCHandleIsClosed) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + ze_ipc_mem_handle_t ipcHandle; + result = context->getIpcMemHandle(ptr, &ipcHandle); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(0u, context->getIPCHandleMap().size()); +} + TEST_F(MemoryIPCTests, givenMultipleCallsToGetIpcHandleWithDeviceAllocationAndCallsToPutIpcHandleThenIpcHandleIsReturnedAndReleased) { size_t size = 10; diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index 581b1cda0d..e3a48737db 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -1058,8 +1058,10 @@ GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromSharedHandle(o } void DrmMemoryManager::closeInternalHandle(uint64_t &handle, uint32_t handleId, GraphicsAllocation *graphicsAllocation) { - DrmAllocation *drmAllocation = static_cast(graphicsAllocation); - drmAllocation->clearInternalHandle(handleId); + if (graphicsAllocation) { + DrmAllocation *drmAllocation = static_cast(graphicsAllocation); + drmAllocation->clearInternalHandle(handleId); + } [[maybe_unused]] auto status = this->closeFunction(static_cast(handle)); DEBUG_BREAK_IF(status != 0); } diff --git a/shared/source/os_interface/windows/wddm_memory_manager.cpp b/shared/source/os_interface/windows/wddm_memory_manager.cpp index 12199820be..dd4a4218f5 100644 --- a/shared/source/os_interface/windows/wddm_memory_manager.cpp +++ b/shared/source/os_interface/windows/wddm_memory_manager.cpp @@ -610,8 +610,10 @@ void WddmMemoryManager::freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation } void WddmMemoryManager::closeInternalHandle(uint64_t &handle, uint32_t handleId, GraphicsAllocation *graphicsAllocation) { - WddmAllocation *wddmAllocation = static_cast(graphicsAllocation); - wddmAllocation->clearInternalHandle(handleId); + if (graphicsAllocation) { + WddmAllocation *wddmAllocation = static_cast(graphicsAllocation); + wddmAllocation->clearInternalHandle(handleId); + } [[maybe_unused]] auto status = SysCalls::closeHandle(reinterpret_cast(reinterpret_cast(handle))); DEBUG_BREAK_IF(!status); } 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 241c570740..30e33e2210 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 @@ -969,6 +969,26 @@ TEST_F(DrmMemoryManagerTest, GivenAllocationWhenClosingInternalHandleThenSucceed memoryManager->freeGraphicsMemory(graphicsAllocation); } +TEST_F(DrmMemoryManagerTest, GivenNoAllocationWhenClosingInternalHandleThenSucceeds) { + mock->ioctlExpected.primeFdToHandle = 1; + mock->ioctlExpected.gemWait = 1; + mock->ioctlExpected.gemClose = 1; + mock->ioctlExpected.handleToPrimeFd = 1; + + osHandle handle = 1u; + uint64_t handleVal = 1u; + this->mock->outputHandle = 2u; + size_t size = 4096u; + AllocationProperties properties(rootDeviceIndex, false, size, AllocationType::SHARED_BUFFER, false, {}); + + auto graphicsAllocation = memoryManager->createGraphicsAllocationFromSharedHandle(handle, properties, false, false, true, nullptr); + EXPECT_EQ(0, graphicsAllocation->createInternalHandle(this->memoryManager, 0u, handleVal)); + + memoryManager->closeInternalHandle(handleVal, 0u, nullptr); + + memoryManager->freeGraphicsMemory(graphicsAllocation); +} + TEST_F(DrmMemoryManagerTest, GivenNullptrDrmAllocationWhenTryingToRegisterItThenRegisterSharedBoHandleAllocationDoesNothing) { ASSERT_TRUE(memoryManager->sharedBoHandles.empty()); diff --git a/shared/test/unit_test/os_interface/wddm_linux/configure_device_address_space_drm_or_wddm_test.cpp b/shared/test/unit_test/os_interface/wddm_linux/configure_device_address_space_drm_or_wddm_test.cpp index 0a24c8da69..1b49518a48 100644 --- a/shared/test/unit_test/os_interface/wddm_linux/configure_device_address_space_drm_or_wddm_test.cpp +++ b/shared/test/unit_test/os_interface/wddm_linux/configure_device_address_space_drm_or_wddm_test.cpp @@ -709,6 +709,29 @@ TEST_F(WddmLinuxTest, givenAllocatedMemoryAndCloseInternalHandleThenSharedHandle memoryManager.freeGraphicsMemoryImpl(alloc); } +TEST_F(WddmLinuxTest, givenAllocatedMemoryAndCloseInternalHandleWihtoutAllocationThenSharedHandleStillClosed) { + osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock; + osEnvironment->gdi->createAllocation2 = createAllocation2Mock; + osEnvironment->gdi->mapGpuVirtualAddress = mapGpuVirtualAddressMock; + osEnvironment->gdi->lock2 = lock2Mock; + osEnvironment->gdi->destroyAllocation2 = destroyAllocations2Mock; + + MockWddmLinuxMemoryManager memoryManager{mockExecEnv}; + + NEO::AllocationData allocData = {}; + NEO::MemoryManager::AllocationStatus status = NEO::MemoryManager::AllocationStatus::Error; + allocData.size = 3U; + + auto alloc = memoryManager.allocatePhysicalDeviceMemory(allocData, status); + ASSERT_NE(nullptr, alloc); + uint64_t handle = 0; + EXPECT_EQ(0, alloc->createInternalHandle(&memoryManager, 0u, handle)); + + memoryManager.closeInternalHandle(handle, 0u, nullptr); + + memoryManager.freeGraphicsMemoryImpl(alloc); +} + TEST_F(WddmLinuxTest, givenAllocatedMemoryAndCreateInternalHandleFailedThenEmpyHandleReturned) { osEnvironment->gdi->reserveGpuVirtualAddress = reserveDeviceAddressSpaceMock; osEnvironment->gdi->createAllocation2 = createAllocation2Mock; diff --git a/shared/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp b/shared/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp index b42102bdb8..f066c29c92 100644 --- a/shared/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp +++ b/shared/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp @@ -230,6 +230,21 @@ TEST_F(WddmMemoryManagerAllocPathTests, GivenValidAllocationThenCreateInternalHa memoryManager->freeGraphicsMemory(graphicsAllocation); } +TEST_F(WddmMemoryManagerAllocPathTests, GivenNoAllocationThenCreateInternalHandleSucceeds) { + NEO::AllocationData allocData = {}; + allocData.type = NEO::AllocationType::SVM_CPU; + allocData.forceKMDAllocation = true; + allocData.makeGPUVaDifferentThanCPUPtr = true; + auto graphicsAllocation = memoryManager->allocateGraphicsMemoryUsingKmdAndMapItToCpuVA(allocData, false); + + uint64_t handle = 0; + EXPECT_EQ(0, graphicsAllocation->createInternalHandle(memoryManager, 0u, handle)); + + memoryManager->closeInternalHandle(handle, 0u, nullptr); + + memoryManager->freeGraphicsMemory(graphicsAllocation); +} + TEST_F(WddmMemoryManagerAllocPathTests, GivenValidAllocationThenCreateInternalHandleSucceedsAfterMultipleCallsToCreate) { NEO::AllocationData allocData = {}; allocData.type = NEO::AllocationType::SVM_CPU;