From da506f5932fc2a3d7cac92ba76a25397c15c1a01 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 14 Mar 2020 22:31:31 +0100 Subject: [PATCH] [util] Add generic recursive spinlock --- src/d3d10/d3d10_include.h | 2 ++ src/d3d10/d3d10_multithread.cpp | 32 ---------------------------- src/d3d10/d3d10_multithread.h | 30 +++----------------------- src/d3d9/d3d9_include.h | 2 ++ src/d3d9/d3d9_multithread.cpp | 32 ---------------------------- src/d3d9/d3d9_multithread.h | 30 +++----------------------- src/util/meson.build | 2 ++ src/util/sync/sync_recursive.cpp | 36 ++++++++++++++++++++++++++++++++ src/util/sync/sync_recursive.h | 32 ++++++++++++++++++++++++++++ 9 files changed, 80 insertions(+), 118 deletions(-) create mode 100644 src/util/sync/sync_recursive.cpp create mode 100644 src/util/sync/sync_recursive.h diff --git a/src/d3d10/d3d10_include.h b/src/d3d10/d3d10_include.h index bb78d6a1..17143a08 100644 --- a/src/d3d10/d3d10_include.h +++ b/src/d3d10/d3d10_include.h @@ -1,7 +1,9 @@ #pragma once #include "../dxgi/dxgi_include.h" + #include "../util/sync/sync_spinlock.h" +#include "../util/sync/sync_recursive.h" #include #include diff --git a/src/d3d10/d3d10_multithread.cpp b/src/d3d10/d3d10_multithread.cpp index bc93e92e..f38a8081 100644 --- a/src/d3d10/d3d10_multithread.cpp +++ b/src/d3d10/d3d10_multithread.cpp @@ -2,38 +2,6 @@ namespace dxvk { - void D3D10DeviceMutex::lock() { - while (!try_lock()) - dxvk::this_thread::yield(); - } - - - void D3D10DeviceMutex::unlock() { - if (likely(m_counter == 0)) - m_owner.store(0, std::memory_order_release); - else - m_counter -= 1; - } - - - bool D3D10DeviceMutex::try_lock() { - uint32_t threadId = GetCurrentThreadId(); - uint32_t expected = 0; - - bool status = m_owner.compare_exchange_weak( - expected, threadId, std::memory_order_acquire); - - if (status) - return true; - - if (expected != threadId) - return false; - - m_counter += 1; - return true; - } - - D3D10Multithread::D3D10Multithread( IUnknown* pParent, BOOL Protected) diff --git a/src/d3d10/d3d10_multithread.h b/src/d3d10/d3d10_multithread.h index f29ee8c7..39a736cc 100644 --- a/src/d3d10/d3d10_multithread.h +++ b/src/d3d10/d3d10_multithread.h @@ -4,30 +4,6 @@ namespace dxvk { - /** - * \brief Device mutex - * - * Effectively implements a recursive spinlock - * which is used to lock the D3D10 device. - */ - class D3D10DeviceMutex { - - public: - - void lock(); - - void unlock(); - - bool try_lock(); - - private: - - std::atomic m_owner = { 0u }; - uint32_t m_counter = { 0u }; - - }; - - /** * \brief Device lock * @@ -43,7 +19,7 @@ namespace dxvk { D3D10DeviceLock() : m_mutex(nullptr) { } - D3D10DeviceLock(D3D10DeviceMutex& mutex) + D3D10DeviceLock(sync::RecursiveSpinlock& mutex) : m_mutex(&mutex) { mutex.lock(); } @@ -69,7 +45,7 @@ namespace dxvk { private: - D3D10DeviceMutex* m_mutex; + sync::RecursiveSpinlock* m_mutex; }; @@ -120,7 +96,7 @@ namespace dxvk { IUnknown* m_parent; BOOL m_protected; - D3D10DeviceMutex m_mutex; + sync::RecursiveSpinlock m_mutex; }; diff --git a/src/d3d9/d3d9_include.h b/src/d3d9/d3d9_include.h index 32b36c4d..5449e3ca 100644 --- a/src/d3d9/d3d9_include.h +++ b/src/d3d9/d3d9_include.h @@ -30,6 +30,8 @@ #include "../util/rc/util_rc.h" #include "../util/rc/util_rc_ptr.h" +#include "../util/sync/sync_recursive.h" + #include "../util/util_env.h" #include "../util/util_enum.h" #include "../util/util_error.h" diff --git a/src/d3d9/d3d9_multithread.cpp b/src/d3d9/d3d9_multithread.cpp index 3089e47f..0e10a093 100644 --- a/src/d3d9/d3d9_multithread.cpp +++ b/src/d3d9/d3d9_multithread.cpp @@ -2,38 +2,6 @@ namespace dxvk { - void D3D9DeviceMutex::lock() { - while (!try_lock()) - dxvk::this_thread::yield(); - } - - - void D3D9DeviceMutex::unlock() { - if (likely(m_counter == 0)) - m_owner.store(0, std::memory_order_release); - else - m_counter -= 1; - } - - - bool D3D9DeviceMutex::try_lock() { - uint32_t threadId = GetCurrentThreadId(); - uint32_t expected = 0; - - bool status = m_owner.compare_exchange_weak( - expected, threadId, std::memory_order_acquire); - - if (status) - return true; - - if (expected != threadId) - return false; - - m_counter += 1; - return true; - } - - D3D9Multithread::D3D9Multithread( BOOL Protected) : m_protected( Protected ) { } diff --git a/src/d3d9/d3d9_multithread.h b/src/d3d9/d3d9_multithread.h index 47f8999f..f91857b6 100644 --- a/src/d3d9/d3d9_multithread.h +++ b/src/d3d9/d3d9_multithread.h @@ -4,30 +4,6 @@ namespace dxvk { - /** - * \brief Device mutex - * - * Effectively implements a recursive spinlock - * which is used to lock the D3D9 device. - */ - class D3D9DeviceMutex { - - public: - - void lock(); - - void unlock(); - - bool try_lock(); - - private: - - std::atomic m_owner = { 0u }; - uint32_t m_counter = { 0u }; - - }; - - /** * \brief Device lock * @@ -43,7 +19,7 @@ namespace dxvk { D3D9DeviceLock() : m_mutex(nullptr) { } - D3D9DeviceLock(D3D9DeviceMutex& mutex) + D3D9DeviceLock(sync::RecursiveSpinlock& mutex) : m_mutex(&mutex) { mutex.lock(); } @@ -69,7 +45,7 @@ namespace dxvk { private: - D3D9DeviceMutex* m_mutex; + sync::RecursiveSpinlock* m_mutex; }; @@ -94,7 +70,7 @@ namespace dxvk { BOOL m_protected; - D3D9DeviceMutex m_mutex; + sync::RecursiveSpinlock m_mutex; }; diff --git a/src/util/meson.build b/src/util/meson.build index 80fe0be2..80a424f9 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -16,6 +16,8 @@ util_src = files([ 'sha1/sha1.c', 'sha1/sha1_util.cpp', + + 'sync/sync_recursive.cpp', ]) util_lib = static_library('util', util_src, diff --git a/src/util/sync/sync_recursive.cpp b/src/util/sync/sync_recursive.cpp new file mode 100644 index 00000000..ee6a1265 --- /dev/null +++ b/src/util/sync/sync_recursive.cpp @@ -0,0 +1,36 @@ +#include "sync_recursive.h" +#include "sync_spinlock.h" + +namespace dxvk::sync { + + void RecursiveSpinlock::lock() { + spin(2000, [this] { return try_lock(); }); + } + + + void RecursiveSpinlock::unlock() { + if (likely(m_counter == 0)) + m_owner.store(0, std::memory_order_release); + else + m_counter -= 1; + } + + + bool RecursiveSpinlock::try_lock() { + uint32_t threadId = GetCurrentThreadId(); + uint32_t expected = 0; + + bool status = m_owner.compare_exchange_weak( + expected, threadId, std::memory_order_acquire); + + if (status) + return true; + + if (expected != threadId) + return false; + + m_counter += 1; + return true; + } + +} diff --git a/src/util/sync/sync_recursive.h b/src/util/sync/sync_recursive.h new file mode 100644 index 00000000..1bb64db1 --- /dev/null +++ b/src/util/sync/sync_recursive.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "../com/com_include.h" + +namespace dxvk::sync { + + /** + * \brief Recursive spinlock + * + * Implements a spinlock that can be acquired + * by the same thread multiple times. + */ + class RecursiveSpinlock { + + public: + + void lock(); + + void unlock(); + + bool try_lock(); + + private: + + std::atomic m_owner = { 0u }; + uint32_t m_counter = { 0u }; + + }; + +}