1*5f757f3fSDimitry Andric //===-- condition_variable_linux.cpp ----------------------------*- C++ -*-===// 2*5f757f3fSDimitry Andric // 3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5f757f3fSDimitry Andric // 7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 8*5f757f3fSDimitry Andric 9*5f757f3fSDimitry Andric #include "platform.h" 10*5f757f3fSDimitry Andric 11*5f757f3fSDimitry Andric #if SCUDO_LINUX 12*5f757f3fSDimitry Andric 13*5f757f3fSDimitry Andric #include "condition_variable_linux.h" 14*5f757f3fSDimitry Andric 15*5f757f3fSDimitry Andric #include "atomic_helpers.h" 16*5f757f3fSDimitry Andric 17*5f757f3fSDimitry Andric #include <limits.h> 18*5f757f3fSDimitry Andric #include <linux/futex.h> 19*5f757f3fSDimitry Andric #include <sys/syscall.h> 20*5f757f3fSDimitry Andric #include <unistd.h> 21*5f757f3fSDimitry Andric 22*5f757f3fSDimitry Andric namespace scudo { 23*5f757f3fSDimitry Andric 24*5f757f3fSDimitry Andric void ConditionVariableLinux::notifyAllImpl(UNUSED HybridMutex &M) { 25*5f757f3fSDimitry Andric const u32 V = atomic_load_relaxed(&Counter); 26*5f757f3fSDimitry Andric atomic_store_relaxed(&Counter, V + 1); 27*5f757f3fSDimitry Andric 28*5f757f3fSDimitry Andric // TODO(chiahungduan): Move the waiters from the futex waiting queue 29*5f757f3fSDimitry Andric // `Counter` to futex waiting queue `M` so that the awoken threads won't be 30*5f757f3fSDimitry Andric // blocked again due to locked `M` by current thread. 31*5f757f3fSDimitry Andric if (LastNotifyAll != V) { 32*5f757f3fSDimitry Andric syscall(SYS_futex, reinterpret_cast<uptr>(&Counter), FUTEX_WAKE_PRIVATE, 33*5f757f3fSDimitry Andric INT_MAX, nullptr, nullptr, 0); 34*5f757f3fSDimitry Andric } 35*5f757f3fSDimitry Andric 36*5f757f3fSDimitry Andric LastNotifyAll = V + 1; 37*5f757f3fSDimitry Andric } 38*5f757f3fSDimitry Andric 39*5f757f3fSDimitry Andric void ConditionVariableLinux::waitImpl(HybridMutex &M) { 40*5f757f3fSDimitry Andric const u32 V = atomic_load_relaxed(&Counter) + 1; 41*5f757f3fSDimitry Andric atomic_store_relaxed(&Counter, V); 42*5f757f3fSDimitry Andric 43*5f757f3fSDimitry Andric // TODO: Use ScopedUnlock when it's supported. 44*5f757f3fSDimitry Andric M.unlock(); 45*5f757f3fSDimitry Andric syscall(SYS_futex, reinterpret_cast<uptr>(&Counter), FUTEX_WAIT_PRIVATE, V, 46*5f757f3fSDimitry Andric nullptr, nullptr, 0); 47*5f757f3fSDimitry Andric M.lock(); 48*5f757f3fSDimitry Andric } 49*5f757f3fSDimitry Andric 50*5f757f3fSDimitry Andric } // namespace scudo 51*5f757f3fSDimitry Andric 52*5f757f3fSDimitry Andric #endif // SCUDO_LINUX 53