Commit 46e46627 authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot

Allow the use of an emulated futex for EventCount

Summary:
Otherwise it won't work under MSVC where we don't have Futexes.
This is achieved by using the Futex API already used elsewhere in Folly.

Reviewed By: yfeldblum

Differential Revision: D4233517

fbshipit-source-id: d6ae6a34b2287cf485f8e4a316445a2ba746d1a7
parent 6d58adc5
...@@ -16,30 +16,21 @@ ...@@ -16,30 +16,21 @@
#pragma once #pragma once
#include <syscall.h>
#include <linux/futex.h>
#include <climits>
#include <atomic> #include <atomic>
#include <climits>
#include <thread> #include <thread>
#include <glog/logging.h> #include <glog/logging.h>
#include <folly/Bits.h> #include <folly/Bits.h>
#include <folly/Likely.h> #include <folly/Likely.h>
#include <folly/detail/Futex.h>
#include <folly/portability/SysTime.h> #include <folly/portability/SysTime.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
namespace folly { namespace folly {
namespace detail {
inline int futex(int* uaddr, int op, int val, const timespec* timeout,
int* uaddr2, int val3) noexcept {
return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
}
} // namespace detail
/** /**
* Event count: a condition variable for lock free algorithms. * Event count: a condition variable for lock free algorithms.
* *
...@@ -125,6 +116,8 @@ class EventCount { ...@@ -125,6 +116,8 @@ class EventCount {
static_assert(sizeof(int) == 4, "bad platform"); static_assert(sizeof(int) == 4, "bad platform");
static_assert(sizeof(uint32_t) == 4, "bad platform"); static_assert(sizeof(uint32_t) == 4, "bad platform");
static_assert(sizeof(uint64_t) == 8, "bad platform"); static_assert(sizeof(uint64_t) == 8, "bad platform");
static_assert(sizeof(std::atomic<uint64_t>) == 8, "bad platform");
static_assert(sizeof(detail::Futex<std::atomic>) == 4, "bad platform");
static constexpr size_t kEpochOffset = kIsLittleEndian ? 1 : 0; static constexpr size_t kEpochOffset = kIsLittleEndian ? 1 : 0;
...@@ -150,8 +143,8 @@ inline void EventCount::notifyAll() noexcept { ...@@ -150,8 +143,8 @@ inline void EventCount::notifyAll() noexcept {
inline void EventCount::doNotify(int n) noexcept { inline void EventCount::doNotify(int n) noexcept {
uint64_t prev = val_.fetch_add(kAddEpoch, std::memory_order_acq_rel); uint64_t prev = val_.fetch_add(kAddEpoch, std::memory_order_acq_rel);
if (UNLIKELY(prev & kWaiterMask)) { if (UNLIKELY(prev & kWaiterMask)) {
detail::futex(reinterpret_cast<int*>(&val_) + kEpochOffset, (reinterpret_cast<detail::Futex<std::atomic>*>(&val_) + kEpochOffset)
FUTEX_WAKE, n, nullptr, nullptr, 0); ->futexWake(n);
} }
} }
...@@ -170,8 +163,8 @@ inline void EventCount::cancelWait() noexcept { ...@@ -170,8 +163,8 @@ inline void EventCount::cancelWait() noexcept {
inline void EventCount::wait(Key key) noexcept { inline void EventCount::wait(Key key) noexcept {
while ((val_.load(std::memory_order_acquire) >> kEpochShift) == key.epoch_) { while ((val_.load(std::memory_order_acquire) >> kEpochShift) == key.epoch_) {
detail::futex(reinterpret_cast<int*>(&val_) + kEpochOffset, (reinterpret_cast<detail::Futex<std::atomic>*>(&val_) + kEpochOffset)
FUTEX_WAIT, key.epoch_, nullptr, nullptr, 0); ->futexWait(key.epoch_);
} }
// memory_order_relaxed would suffice for correctness, but the faster // memory_order_relaxed would suffice for correctness, but the faster
// #waiters gets to 0, the less likely it is that we'll do spurious wakeups // #waiters gets to 0, the less likely it is that we'll do spurious wakeups
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment