mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-27 04:54:15 +01:00
[util] Add generic recursive spinlock
This commit is contained in:
parent
55e3240479
commit
da506f5932
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../dxgi/dxgi_include.h"
|
#include "../dxgi/dxgi_include.h"
|
||||||
|
|
||||||
#include "../util/sync/sync_spinlock.h"
|
#include "../util/sync/sync_spinlock.h"
|
||||||
|
#include "../util/sync/sync_recursive.h"
|
||||||
|
|
||||||
#include <d3d10_1.h>
|
#include <d3d10_1.h>
|
||||||
#include <d3d11_1.h>
|
#include <d3d11_1.h>
|
||||||
|
@ -2,38 +2,6 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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(
|
D3D10Multithread::D3D10Multithread(
|
||||||
IUnknown* pParent,
|
IUnknown* pParent,
|
||||||
BOOL Protected)
|
BOOL Protected)
|
||||||
|
@ -4,30 +4,6 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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
|
* \brief Device lock
|
||||||
*
|
*
|
||||||
@ -43,7 +19,7 @@ namespace dxvk {
|
|||||||
D3D10DeviceLock()
|
D3D10DeviceLock()
|
||||||
: m_mutex(nullptr) { }
|
: m_mutex(nullptr) { }
|
||||||
|
|
||||||
D3D10DeviceLock(D3D10DeviceMutex& mutex)
|
D3D10DeviceLock(sync::RecursiveSpinlock& mutex)
|
||||||
: m_mutex(&mutex) {
|
: m_mutex(&mutex) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
}
|
}
|
||||||
@ -69,7 +45,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
D3D10DeviceMutex* m_mutex;
|
sync::RecursiveSpinlock* m_mutex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,7 +96,7 @@ namespace dxvk {
|
|||||||
IUnknown* m_parent;
|
IUnknown* m_parent;
|
||||||
BOOL m_protected;
|
BOOL m_protected;
|
||||||
|
|
||||||
D3D10DeviceMutex m_mutex;
|
sync::RecursiveSpinlock m_mutex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include "../util/rc/util_rc.h"
|
#include "../util/rc/util_rc.h"
|
||||||
#include "../util/rc/util_rc_ptr.h"
|
#include "../util/rc/util_rc_ptr.h"
|
||||||
|
|
||||||
|
#include "../util/sync/sync_recursive.h"
|
||||||
|
|
||||||
#include "../util/util_env.h"
|
#include "../util/util_env.h"
|
||||||
#include "../util/util_enum.h"
|
#include "../util/util_enum.h"
|
||||||
#include "../util/util_error.h"
|
#include "../util/util_error.h"
|
||||||
|
@ -2,38 +2,6 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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(
|
D3D9Multithread::D3D9Multithread(
|
||||||
BOOL Protected)
|
BOOL Protected)
|
||||||
: m_protected( Protected ) { }
|
: m_protected( Protected ) { }
|
||||||
|
@ -4,30 +4,6 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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
|
* \brief Device lock
|
||||||
*
|
*
|
||||||
@ -43,7 +19,7 @@ namespace dxvk {
|
|||||||
D3D9DeviceLock()
|
D3D9DeviceLock()
|
||||||
: m_mutex(nullptr) { }
|
: m_mutex(nullptr) { }
|
||||||
|
|
||||||
D3D9DeviceLock(D3D9DeviceMutex& mutex)
|
D3D9DeviceLock(sync::RecursiveSpinlock& mutex)
|
||||||
: m_mutex(&mutex) {
|
: m_mutex(&mutex) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
}
|
}
|
||||||
@ -69,7 +45,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
D3D9DeviceMutex* m_mutex;
|
sync::RecursiveSpinlock* m_mutex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -94,7 +70,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
BOOL m_protected;
|
BOOL m_protected;
|
||||||
|
|
||||||
D3D9DeviceMutex m_mutex;
|
sync::RecursiveSpinlock m_mutex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ util_src = files([
|
|||||||
|
|
||||||
'sha1/sha1.c',
|
'sha1/sha1.c',
|
||||||
'sha1/sha1_util.cpp',
|
'sha1/sha1_util.cpp',
|
||||||
|
|
||||||
|
'sync/sync_recursive.cpp',
|
||||||
])
|
])
|
||||||
|
|
||||||
util_lib = static_library('util', util_src,
|
util_lib = static_library('util', util_src,
|
||||||
|
36
src/util/sync/sync_recursive.cpp
Normal file
36
src/util/sync/sync_recursive.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
src/util/sync/sync_recursive.h
Normal file
32
src/util/sync/sync_recursive.h
Normal 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 };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user