sanitizer_common: modernize SpinMutex

Some minor improvements:
1. Make StaticSpinMutex non-copyable.
2. Add LIKELY to Lock.
3. Move LockSlow into the .cpp file (now that we have it).
4. The only non-trivial change: use proc_yield(1) instread of proc_yield(10)
   with the proportional increase in the number of spin iterations.
   Latency of the PAUSE instruction has raised from ~1 cycle to ~100 cycles
   in the recent Intel CPUs. So proc_yield(10) is too aggressive backoff.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D106350
This commit is contained in:
Dmitry Vyukov 2021-07-20 10:36:41 +02:00
parent 9226e6f7d2
commit 927efd0b5d
2 changed files with 19 additions and 16 deletions

View File

@ -16,6 +16,18 @@
namespace __sanitizer {
void StaticSpinMutex::LockSlow() {
for (int i = 0;; i++) {
if (i < 100)
proc_yield(1);
else
internal_sched_yield();
if (atomic_load(&state_, memory_order_relaxed) == 0 &&
atomic_exchange(&state_, 1, memory_order_acquire) == 0)
return;
}
}
void Semaphore::Wait() {
u32 count = atomic_load(&state_, memory_order_relaxed);
for (;;) {

View File

@ -22,12 +22,14 @@ namespace __sanitizer {
class MUTEX StaticSpinMutex {
public:
StaticSpinMutex() = default;
void Init() {
atomic_store(&state_, 0, memory_order_relaxed);
}
void Lock() ACQUIRE() {
if (TryLock())
if (LIKELY(TryLock()))
return;
LockSlow();
}
@ -45,17 +47,10 @@ class MUTEX StaticSpinMutex {
private:
atomic_uint8_t state_;
void NOINLINE LockSlow() {
for (int i = 0;; i++) {
if (i < 10)
proc_yield(10);
else
internal_sched_yield();
if (atomic_load(&state_, memory_order_relaxed) == 0
&& atomic_exchange(&state_, 1, memory_order_acquire) == 0)
return;
}
}
void LockSlow();
StaticSpinMutex(const StaticSpinMutex &) = delete;
void operator=(const StaticSpinMutex &) = delete;
};
class MUTEX SpinMutex : public StaticSpinMutex {
@ -63,10 +58,6 @@ class MUTEX SpinMutex : public StaticSpinMutex {
SpinMutex() {
Init();
}
private:
SpinMutex(const SpinMutex &) = delete;
void operator=(const SpinMutex &) = delete;
};
// Semaphore provides an OS-dependent way to park/unpark threads.