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