1 //===--- Futex Wrapper ------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H
10 #define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H
12 #include "src/__support/CPP/atomic.h"
13 #include "src/__support/CPP/limits.h"
14 #include "src/__support/CPP/optional.h"
15 #include "src/__support/OSUtil/syscall.h"
16 #include "src/__support/macros/attributes.h"
17 #include "src/__support/macros/config.h"
18 #include "src/__support/threads/linux/futex_word.h"
19 #include "src/__support/time/linux/abs_timeout.h"
20 #include <linux/errno.h>
21 #include <linux/futex.h>
23 namespace LIBC_NAMESPACE_DECL
{
24 class Futex
: public cpp::Atomic
<FutexWordType
> {
26 using Timeout
= internal::AbsTimeout
;
27 LIBC_INLINE
constexpr Futex(FutexWordType value
)
28 : cpp::Atomic
<FutexWordType
>(value
) {}
29 LIBC_INLINE Futex
&operator=(FutexWordType value
) {
30 cpp::Atomic
<FutexWordType
>::store(value
);
33 LIBC_INLINE
long wait(FutexWordType expected
,
34 cpp::optional
<Timeout
> timeout
= cpp::nullopt
,
35 bool is_shared
= false) {
36 // use bitset variants to enforce abs_time
37 uint32_t op
= is_shared
? FUTEX_WAIT_BITSET
: FUTEX_WAIT_BITSET_PRIVATE
;
38 if (timeout
&& timeout
->is_realtime()) {
39 op
|= FUTEX_CLOCK_REALTIME
;
42 if (this->load(cpp::MemoryOrder::RELAXED
) != expected
)
45 long ret
= syscall_impl
<long>(
46 /* syscall number */ FUTEX_SYSCALL_ID
,
47 /* futex address */ this,
48 /* futex operation */ op
,
49 /* expected value */ expected
,
50 /* timeout */ timeout
? &timeout
->get_timespec() : nullptr,
51 /* ignored */ nullptr,
52 /* bitset */ FUTEX_BITSET_MATCH_ANY
);
54 // continue waiting if interrupted; otherwise return the result
55 // which should normally be 0 or -ETIMEOUT
62 LIBC_INLINE
long notify_one(bool is_shared
= false) {
63 return syscall_impl
<long>(
64 /* syscall number */ FUTEX_SYSCALL_ID
,
65 /* futex address */ this,
66 /* futex operation */ is_shared
? FUTEX_WAKE
: FUTEX_WAKE_PRIVATE
,
67 /* wake up limit */ 1,
68 /* ignored */ nullptr,
69 /* ignored */ nullptr,
72 LIBC_INLINE
long notify_all(bool is_shared
= false) {
73 return syscall_impl
<long>(
74 /* syscall number */ FUTEX_SYSCALL_ID
,
75 /* futex address */ this,
76 /* futex operation */ is_shared
? FUTEX_WAKE
: FUTEX_WAKE_PRIVATE
,
77 /* wake up limit */ cpp::numeric_limits
<int>::max(),
78 /* ignored */ nullptr,
79 /* ignored */ nullptr,
84 static_assert(__is_standard_layout(Futex
),
85 "Futex must be a standard layout type.");
86 } // namespace LIBC_NAMESPACE_DECL
88 #endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H