28 #include <linux/futex.h> 46 #ifndef FUTEX_WAIT_BITSET 47 #define FUTEX_WAIT_BITSET 9 49 #ifndef FUTEX_WAKE_BITSET 50 #define FUTEX_WAKE_BITSET 10 52 #ifndef FUTEX_PRIVATE_FLAG 53 #define FUTEX_PRIVATE_FLAG 128 55 #ifndef FUTEX_CLOCK_REALTIME 56 #define FUTEX_CLOCK_REALTIME 256 63 FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG,
79 template <
class Clock>
80 struct timespec timeSpecFromTimePoint(time_point<Clock> absTime) {
81 auto epoch = absTime.time_since_epoch();
82 if (epoch.count() < 0) {
84 epoch = Clock::duration::zero();
90 using time_t_seconds = duration<std::time_t, seconds::period>;
91 using long_nanos = duration<long int, nanoseconds::period>;
93 auto secs = duration_cast<time_t_seconds>(epoch);
94 auto nanos = duration_cast<long_nanos>(epoch - secs);
95 struct timespec result = {secs.count(), nanos.count()};
102 system_clock::time_point
const* absSystemTime,
103 steady_clock::time_point
const* absSteadyTime,
105 assert(absSystemTime ==
nullptr || absSteadyTime ==
nullptr);
107 int op = FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG;
109 struct timespec*
timeout =
nullptr;
111 if (absSystemTime !=
nullptr) {
112 op |= FUTEX_CLOCK_REALTIME;
113 ts = timeSpecFromTimePoint(*absSystemTime);
115 }
else if (absSteadyTime !=
nullptr) {
116 ts = timeSpecFromTimePoint(*absSteadyTime);
132 return FutexResult::AWOKEN;
136 assert(timeout !=
nullptr);
137 return FutexResult::TIMEDOUT;
139 return FutexResult::INTERRUPTED;
141 return FutexResult::VALUE_CHANGED;
152 return FutexResult::VALUE_CHANGED;
162 using Lot = ParkingLot<uint32_t>;
165 int emulatedFutexWake(
const void* addr,
int count,
uint32_t waitMask) {
167 parkingLot.unpark(addr, [&](
const uint32_t& mask) {
168 if ((mask & waitMask) == 0) {
169 return UnparkControl::RetainContinue;
174 return count > 0 ? UnparkControl::RemoveContinue
175 : UnparkControl::RemoveBreak;
180 template <
typename F>
184 system_clock::time_point
const* absSystemTime,
185 steady_clock::time_point
const* absSteadyTime,
188 std::is_same<F,
const Futex<std::atomic>>::
value ||
189 std::is_same<F,
const Futex<EmulatedFutexAtomic>>::
value,
190 "Type F must be either Futex<std::atomic> or Futex<EmulatedFutexAtomic>");
193 res = parkingLot.park_until(
196 [&] {
return *futex == expected; },
199 }
else if (absSteadyTime) {
200 res = parkingLot.park_until(
203 [&] {
return *futex == expected; },
207 res = parkingLot.park(
208 futex, waitMask, [&] {
return *futex == expected; }, [] {});
212 return FutexResult::VALUE_CHANGED;
213 case ParkResult::Unpark:
214 return FutexResult::AWOKEN;
215 case ParkResult::Timeout:
216 return FutexResult::TIMEDOUT;
219 return FutexResult::INTERRUPTED;
232 return nativeFutexWake(futex, count, wakeMask);
234 return emulatedFutexWake(futex, count, wakeMask);
242 return emulatedFutexWake(futex, count, wakeMask);
248 system_clock::time_point
const* absSystemTime,
249 steady_clock::time_point
const* absSteadyTime,
252 return nativeFutexWaitImpl(
253 futex, expected, absSystemTime, absSteadyTime, waitMask);
255 return emulatedFutexWaitImpl(
256 futex, expected, absSystemTime, absSteadyTime, waitMask);
263 system_clock::time_point
const* absSystemTime,
264 steady_clock::time_point
const* absSteadyTime,
266 return emulatedFutexWaitImpl(
267 futex, expected, absSystemTime, absSteadyTime, waitMask);
Atom< std::uint32_t > Futex
def Skip(lines, pos, regex)
int futexWakeImpl(const Futex< std::atomic > *futex, int count, uint32_t wakeMask)
—— Concurrent Priority Queue Implementation ——
ParkingLot< std::uint32_t > parkingLot
static const char *const value
FutexResult futexWaitImpl(const Futex< EmulatedFutexAtomic > *futex, uint32_t expected, system_clock::time_point const *absSystemTime, steady_clock::time_point const *absSteadyTime, uint32_t waitMask)
ThreadPoolListHook * addr