diff --git a/compiler-rt/lib/scudo/standalone/condition_variable_linux.cpp b/compiler-rt/lib/scudo/standalone/condition_variable_linux.cpp --- a/compiler-rt/lib/scudo/standalone/condition_variable_linux.cpp +++ b/compiler-rt/lib/scudo/standalone/condition_variable_linux.cpp @@ -19,28 +19,38 @@ #include #include -namespace scudo { +// FIXME +#include "string_utils.h" -void ConditionVariableLinux::notifyAllImpl(UNUSED HybridMutex &M) { - u32 V = atomic_exchange(&CurState, State::AllAwoken, memory_order_acq_rel); +namespace scudo { - // TODO(chiahungduan): Move the waiters from the futex waiting queue - // `CurState` to futex waiting queue `M` so that the awoken threads won't be - // blocked again due to locked `M` by current thread. - if (V == State::Waiting) { - syscall(SYS_futex, reinterpret_cast(&CurState), FUTEX_WAKE_PRIVATE, - INT_MAX, nullptr, nullptr, 0); +void ConditionVariableLinux::notifyAllImpl(HybridMutex &M) { + u32 V = atomic_load(&CurState, memory_order_relaxed); + + if (V != 0) { + long NumMoved = syscall(SYS_futex, reinterpret_cast(&CurState), + FUTEX_CMP_REQUEUE_PRIVATE, /* Threads to wake */ 0, + /* Threads to requeue */ INT_MAX, + reinterpret_cast(&M.M), V); + DCHECK_NE(NumMoved, -1L); + V = static_cast(NumMoved); + atomic_fetch_add(&M.M, V << 1, memory_order_release); } } void ConditionVariableLinux::waitImpl(HybridMutex &M) { - atomic_exchange(&CurState, State::Waiting, memory_order_acq_rel); + // atomic_exchange(&CurState, State::Waiting, memory_order_acq_rel); + + u32 V = atomic_fetch_add(&CurState, 1U, memory_order_relaxed); + V += 1; // TODO: Use ScopedUnlock when it's supported. M.unlock(); - syscall(SYS_futex, reinterpret_cast(&CurState), FUTEX_WAIT_PRIVATE, - State::Waiting, nullptr, nullptr, 0); + + syscall(SYS_futex, reinterpret_cast(&CurState), FUTEX_WAIT_PRIVATE, V, + nullptr, nullptr, 0); M.lock(); + atomic_fetch_sub(&CurState, 1U, memory_order_relaxed); } } // namespace scudo diff --git a/compiler-rt/lib/scudo/standalone/mutex.h b/compiler-rt/lib/scudo/standalone/mutex.h --- a/compiler-rt/lib/scudo/standalone/mutex.h +++ b/compiler-rt/lib/scudo/standalone/mutex.h @@ -59,6 +59,7 @@ static constexpr u8 NumberOfYields = 0U; #if SCUDO_LINUX + friend class ConditionVariableLinux; atomic_u32 M = {}; #elif SCUDO_FUCHSIA sync_mutex_t M = {};