File indexing completed on 2025-01-30 09:31:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
0015 #define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
0016
0017 #include "absl/base/config.h"
0018
0019 #ifndef _WIN32
0020 #include <sys/time.h>
0021 #include <unistd.h>
0022 #endif
0023
0024 #ifdef __linux__
0025 #include <linux/futex.h>
0026 #include <sys/syscall.h>
0027 #endif
0028
0029 #include <errno.h>
0030 #include <stdio.h>
0031 #include <time.h>
0032
0033 #include <atomic>
0034 #include <cstdint>
0035 #include <limits>
0036
0037 #include "absl/base/optimization.h"
0038 #include "absl/synchronization/internal/kernel_timeout.h"
0039
0040 #ifdef ABSL_INTERNAL_HAVE_FUTEX
0041 #error ABSL_INTERNAL_HAVE_FUTEX may not be set on the command line
0042 #elif defined(__BIONIC__)
0043
0044
0045 #define ABSL_INTERNAL_HAVE_FUTEX
0046 #elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
0047
0048 #define ABSL_INTERNAL_HAVE_FUTEX
0049 #endif
0050
0051 #ifdef ABSL_INTERNAL_HAVE_FUTEX
0052
0053 namespace absl {
0054 ABSL_NAMESPACE_BEGIN
0055 namespace synchronization_internal {
0056
0057
0058
0059 #ifdef __BIONIC__
0060 #ifndef SYS_futex
0061 #define SYS_futex __NR_futex
0062 #endif
0063 #ifndef FUTEX_WAIT_BITSET
0064 #define FUTEX_WAIT_BITSET 9
0065 #endif
0066 #ifndef FUTEX_PRIVATE_FLAG
0067 #define FUTEX_PRIVATE_FLAG 128
0068 #endif
0069 #ifndef FUTEX_CLOCK_REALTIME
0070 #define FUTEX_CLOCK_REALTIME 256
0071 #endif
0072 #ifndef FUTEX_BITSET_MATCH_ANY
0073 #define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
0074 #endif
0075 #endif
0076
0077 #if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
0078 #define SYS_futex_time64 __NR_futex_time64
0079 #endif
0080
0081 #if defined(SYS_futex_time64) && !defined(SYS_futex)
0082 #define SYS_futex SYS_futex_time64
0083 using FutexTimespec = struct timespec;
0084 #else
0085
0086
0087
0088
0089
0090
0091 struct FutexTimespec {
0092 long tv_sec;
0093 long tv_nsec;
0094 };
0095 #endif
0096
0097 class FutexImpl {
0098 public:
0099
0100
0101 static int Wait(std::atomic<int32_t>* v, int32_t val) {
0102 return WaitAbsoluteTimeout(v, val, nullptr);
0103 }
0104
0105
0106
0107 static int WaitAbsoluteTimeout(std::atomic<int32_t>* v, int32_t val,
0108 const struct timespec* abs_timeout) {
0109 FutexTimespec ts;
0110
0111
0112 auto err = syscall(
0113 SYS_futex, reinterpret_cast<int32_t*>(v),
0114 FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
0115 ToFutexTimespec(abs_timeout, &ts), nullptr, FUTEX_BITSET_MATCH_ANY);
0116 if (err != 0) {
0117 return -errno;
0118 }
0119 return 0;
0120 }
0121
0122
0123
0124 static int WaitRelativeTimeout(std::atomic<int32_t>* v, int32_t val,
0125 const struct timespec* rel_timeout) {
0126 FutexTimespec ts;
0127
0128
0129 auto err =
0130 syscall(SYS_futex, reinterpret_cast<int32_t*>(v), FUTEX_PRIVATE_FLAG,
0131 val, ToFutexTimespec(rel_timeout, &ts));
0132 if (err != 0) {
0133 return -errno;
0134 }
0135 return 0;
0136 }
0137
0138
0139 static int Wake(std::atomic<int32_t>* v, int32_t count) {
0140 auto err = syscall(SYS_futex, reinterpret_cast<int32_t*>(v),
0141 FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
0142 if (ABSL_PREDICT_FALSE(err < 0)) {
0143 return -errno;
0144 }
0145 return 0;
0146 }
0147
0148 private:
0149 static FutexTimespec* ToFutexTimespec(const struct timespec* userspace_ts,
0150 FutexTimespec* futex_ts) {
0151 if (userspace_ts == nullptr) {
0152 return nullptr;
0153 }
0154
0155 using FutexSeconds = decltype(futex_ts->tv_sec);
0156 using FutexNanoseconds = decltype(futex_ts->tv_nsec);
0157
0158 constexpr auto kMaxSeconds{(std::numeric_limits<FutexSeconds>::max)()};
0159 if (userspace_ts->tv_sec > kMaxSeconds) {
0160 futex_ts->tv_sec = kMaxSeconds;
0161 } else {
0162 futex_ts->tv_sec = static_cast<FutexSeconds>(userspace_ts->tv_sec);
0163 }
0164 futex_ts->tv_nsec = static_cast<FutexNanoseconds>(userspace_ts->tv_nsec);
0165 return futex_ts;
0166 }
0167 };
0168
0169 class Futex : public FutexImpl {};
0170
0171 }
0172 ABSL_NAMESPACE_END
0173 }
0174
0175 #endif
0176
0177 #endif