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
notifyAllImpl(UNUSED HybridMutex & M)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
waitImpl(HybridMutex & M)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