diff --git a/src/common/adaptive_mutex.h b/src/common/adaptive_mutex.h index f174f5996..2ab385bdb 100644 --- a/src/common/adaptive_mutex.h +++ b/src/common/adaptive_mutex.h @@ -18,6 +18,9 @@ public: void unlock() { pthread_mutex_unlock(&mutex); } + [[nodiscard]] bool try_lock() { + return pthread_mutex_trylock(&mutex) == 0; + } private: pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index 6908a4cd2..9a1aa1df3 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "common/assert.h" #include "common/debug.h" #include "common/signal_context.h" @@ -194,11 +195,14 @@ struct PageManager::Impl { size_t page = addr >> PAGE_BITS; const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE); - const size_t lock_start = page / PAGES_PER_LOCK; + // Acquire locks for the range of pages + size_t lock_start = page / PAGES_PER_LOCK; const size_t lock_end = Common::DivCeil(page_end, PAGES_PER_LOCK); - for (size_t i = lock_start; i < lock_end; ++i) { - locks[i].lock(); + boost::container::small_vector, 8> unique_locks; + for (; lock_start < lock_end; ++lock_start) { + unique_locks.emplace_back(locks[lock_start], std::defer_lock); } + boost::lock(unique_locks.begin(), unique_locks.end()); auto perms = cached_pages[page].Perm(); u64 range_begin = 0; @@ -251,11 +255,6 @@ struct PageManager::Impl { // Add pending (un)protect action release_pending(); - - // Unlock all locks - for (size_t i = lock_start; i < lock_end; ++i) { - locks[i].unlock(); - } } template