89 lines · c
1//===--- Futex Wrapper ------------------------------------------*- C++ -*-===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H10#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H11 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>22 23namespace LIBC_NAMESPACE_DECL {24class Futex : public cpp::Atomic<FutexWordType> {25public: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);31 return *this;32 }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_time37 uint32_t op = is_shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE;38 if (timeout && timeout->is_realtime()) {39 op |= FUTEX_CLOCK_REALTIME;40 }41 for (;;) {42 if (this->load(cpp::MemoryOrder::RELAXED) != expected)43 return 0;44 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);53 54 // continue waiting if interrupted; otherwise return the result55 // which should normally be 0 or -ETIMEOUT56 if (ret == -EINTR)57 continue;58 59 return ret;60 }61 }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,70 /* ignored */ 0);71 }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,80 /* ignored */ 0);81 }82};83 84static_assert(__is_standard_layout(Futex),85 "Futex must be a standard layout type.");86} // namespace LIBC_NAMESPACE_DECL87 88#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_FUTEX_UTILS_H89