xref: /freebsd/contrib/llvm-project/compiler-rt/lib/scudo/standalone/condition_variable_linux.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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