From dc9bcb99c99493b75cebc23a5cf9d6e661f61f14 Mon Sep 17 00:00:00 2001 From: Jaime Arteaga Date: Wed, 6 Oct 2021 00:37:16 +0000 Subject: [PATCH] Avoid deadlock when evicting unused allocations Signed-off-by: Jaime Arteaga --- shared/source/os_interface/linux/drm_buffer_object.cpp | 4 ++-- .../os_interface/linux/drm_memory_operations_handler.h | 2 +- .../linux/drm_memory_operations_handler_bind.cpp | 8 ++++++-- .../linux/drm_memory_operations_handler_bind.h | 2 +- .../linux/drm_memory_operations_handler_default.cpp | 2 +- .../linux/drm_memory_operations_handler_default.h | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/shared/source/os_interface/linux/drm_buffer_object.cpp b/shared/source/os_interface/linux/drm_buffer_object.cpp index 9b52f4fd29..52b7f0f60d 100644 --- a/shared/source/os_interface/linux/drm_buffer_object.cpp +++ b/shared/source/os_interface/linux/drm_buffer_object.cpp @@ -151,12 +151,12 @@ int BufferObject::exec(uint32_t used, size_t startOffset, unsigned int flags, bo int ret = this->drm->ioctl(DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); if (ret != 0) { - static_cast(this->drm->getRootDeviceEnvironment().memoryOperationsInterface.get())->evictUnusedAllocations(false); + static_cast(this->drm->getRootDeviceEnvironment().memoryOperationsInterface.get())->evictUnusedAllocations(false, true); ret = this->drm->ioctl(DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); } if (ret != 0) { - static_cast(this->drm->getRootDeviceEnvironment().memoryOperationsInterface.get())->evictUnusedAllocations(true); + static_cast(this->drm->getRootDeviceEnvironment().memoryOperationsInterface.get())->evictUnusedAllocations(true, true); ret = this->drm->ioctl(DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); } diff --git a/shared/source/os_interface/linux/drm_memory_operations_handler.h b/shared/source/os_interface/linux/drm_memory_operations_handler.h index df3cbd4342..80b7f00255 100644 --- a/shared/source/os_interface/linux/drm_memory_operations_handler.h +++ b/shared/source/os_interface/linux/drm_memory_operations_handler.h @@ -23,7 +23,7 @@ class DrmMemoryOperationsHandler : public MemoryOperationsHandler { virtual void mergeWithResidencyContainer(OsContext *osContext, ResidencyContainer &residencyContainer) = 0; virtual std::unique_lock lockHandlerIfUsed() = 0; - virtual void evictUnusedAllocations(bool waitForCompletion) = 0; + virtual void evictUnusedAllocations(bool waitForCompletion, bool isLockNeeded) = 0; static std::unique_ptr create(Drm &drm, uint32_t rootDeviceIndex); diff --git a/shared/source/os_interface/linux/drm_memory_operations_handler_bind.cpp b/shared/source/os_interface/linux/drm_memory_operations_handler_bind.cpp index 850bd8b94f..709cdf52a3 100644 --- a/shared/source/os_interface/linux/drm_memory_operations_handler_bind.cpp +++ b/shared/source/os_interface/linux/drm_memory_operations_handler_bind.cpp @@ -110,10 +110,14 @@ std::unique_lock DrmMemoryOperationsHandlerBind::lockHandlerIfUsed() return std::unique_lock(); } -void DrmMemoryOperationsHandlerBind::evictUnusedAllocations(bool waitForCompletion) { +void DrmMemoryOperationsHandlerBind::evictUnusedAllocations(bool waitForCompletion, bool isLockNeeded) { auto memoryManager = static_cast(this->rootDeviceEnvironment.executionEnvironment.memoryManager.get()); - std::lock_guard lock(mutex); + std::unique_lock evictLock(mutex, std::defer_lock); + if (isLockNeeded) { + evictLock.lock(); + } + auto allocLock = memoryManager->acquireAllocLock(); this->evictUnusedAllocationsImpl(memoryManager->getSysMemAllocs(), waitForCompletion); diff --git a/shared/source/os_interface/linux/drm_memory_operations_handler_bind.h b/shared/source/os_interface/linux/drm_memory_operations_handler_bind.h index fecdcbe08d..6ca09f8d44 100644 --- a/shared/source/os_interface/linux/drm_memory_operations_handler_bind.h +++ b/shared/source/os_interface/linux/drm_memory_operations_handler_bind.h @@ -25,7 +25,7 @@ class DrmMemoryOperationsHandlerBind : public DrmMemoryOperationsHandler { void mergeWithResidencyContainer(OsContext *osContext, ResidencyContainer &residencyContainer) override; std::unique_lock lockHandlerIfUsed() override; - void evictUnusedAllocations(bool waitForCompletion) override; + void evictUnusedAllocations(bool waitForCompletion, bool isLockNeeded) override; protected: void evictImpl(OsContext *osContext, GraphicsAllocation &gfxAllocation, DeviceBitfield deviceBitfield); diff --git a/shared/source/os_interface/linux/drm_memory_operations_handler_default.cpp b/shared/source/os_interface/linux/drm_memory_operations_handler_default.cpp index b948bb6e07..9d48e2710b 100644 --- a/shared/source/os_interface/linux/drm_memory_operations_handler_default.cpp +++ b/shared/source/os_interface/linux/drm_memory_operations_handler_default.cpp @@ -64,7 +64,7 @@ std::unique_lock DrmMemoryOperationsHandlerDefault::lockHandlerIfUse return std::unique_lock(); } -void DrmMemoryOperationsHandlerDefault::evictUnusedAllocations(bool waitForCompletion) { +void DrmMemoryOperationsHandlerDefault::evictUnusedAllocations(bool waitForCompletion, bool isLockNeeded) { } } // namespace NEO diff --git a/shared/source/os_interface/linux/drm_memory_operations_handler_default.h b/shared/source/os_interface/linux/drm_memory_operations_handler_default.h index 47a435e7f1..fcf133d08b 100644 --- a/shared/source/os_interface/linux/drm_memory_operations_handler_default.h +++ b/shared/source/os_interface/linux/drm_memory_operations_handler_default.h @@ -26,7 +26,7 @@ class DrmMemoryOperationsHandlerDefault : public DrmMemoryOperationsHandler { void mergeWithResidencyContainer(OsContext *osContext, ResidencyContainer &residencyContainer) override; std::unique_lock lockHandlerIfUsed() override; - void evictUnusedAllocations(bool waitForCompletion) override; + void evictUnusedAllocations(bool waitForCompletion, bool isLockNeeded) override; protected: std::unordered_set residency;