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