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