brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · 943a99a Raw
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