[util] Add generic recursive spinlock

This commit is contained in:
Philip Rebohle 2020-03-14 22:31:31 +01:00 committed by Philip Rebohle
parent 55e3240479
commit da506f5932
9 changed files with 80 additions and 118 deletions

View File

@ -1,7 +1,9 @@
#pragma once
#include "../dxgi/dxgi_include.h"
#include "../util/sync/sync_spinlock.h"
#include "../util/sync/sync_recursive.h"
#include <d3d10_1.h>
#include <d3d11_1.h>

View File

@ -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)

View File

@ -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<uint32_t> 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;
};

View File

@ -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"

View File

@ -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 ) { }

View File

@ -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<uint32_t> 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;
};

View File

@ -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,

View File

@ -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;
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <atomic>
#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<uint32_t> m_owner = { 0u };
uint32_t m_counter = { 0u };
};
}