[util] Improve Spinlock implementation

Addresses two potential issues:
- Our spinlocks are almost never contested, however the code generated
  is not ideal without the likely/unlikely hints.
- In the unlike event that a spinlock is in fact contested, we'd yield
  immediately, even though most of the time we'd only have to wait for
  a few hundred cycles at most.

Replacing our spinlocks with std::mutex is not an option due to much
higher locking overhead in the uncontested case; doing so reduces
performance significantly for the buffer slice and pipeline locks.
parent 9541aef0
Pipeline #984 passed with stage
in 5 minutes and 38 seconds
......@@ -13,7 +13,7 @@ namespace dxvk::sync {
* in case the structure is not likely contested.
*/
class Spinlock {
constexpr static uint32_t SpinCount = 200;
public:
Spinlock() { }
......@@ -23,8 +23,14 @@ namespace dxvk::sync {
Spinlock& operator = (const Spinlock&) = delete;
void lock() {
while (!this->try_lock())
while (unlikely(!try_lock())) {
for (uint32_t i = 1; i < SpinCount; i++) {
if (try_lock())
return;
}
dxvk::this_thread::yield();
}
}
void unlock() {
......@@ -32,8 +38,8 @@ namespace dxvk::sync {
}
bool try_lock() {
return !m_lock.load()
&& !m_lock.exchange(1, std::memory_order_acquire);
return likely(!m_lock.load())
&& likely(!m_lock.exchange(1, std::memory_order_acquire));
}
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment