add emulation of futex() for non-Linux systems
Summary:
Inside the Linux kernel, futex() works by hashing the source
address to a fixed set of wakeup lists. When using folly on non-Linux
systems we can emulate something similar by using std::mutex and
std::condition_variable.
Emulating futex() using higher-level APIs is less crazy than it sounds,
because the emulated futex still provides the advantages of the real
one: it allows all of the fast-paths of a new synchronization construct
to be inlined; it is space efficient, taking only 1 word and allowing
the caller to encode state into all of the word's bits; and it avoids
system calls unless a thread actually needs to be put to sleep or
woken up. Think of this as a way of boostrapping something with the
same properties as futex() on platforms that don't expose it publically.
(Presumably these platforms have private APIs that do something similar.)
This diff moves all of the Linux-specific futex stuff into Futex.cpp,
where it is gated by #ifdef __linux__. It also adds an emulated
implementation. The emulated futex will be selected by default on
non-Linux platforms, or it can be used on Linux by using an Atom template
type of folly::detail::EmulatedFutexAtomic. This means, for example,
that you can test MPMCQueue on top of the emulated API by instantiating
a MPMCQueue<ElemType, EmulatedFutexAtomic>.
As a bonus, this refactoring provides a small speed boost by removing
an unnecessary evaluation of the errno macro in the success path of
futexWait.
Test Plan:
1. existing unit tests
2. new unit tests (including tests of Futex users)
3. compile Futex.cpp on OS X (some other build failures still occur)
Reviewed By: delong.j@fb.com
Subscribers: trunkagent, njormrod, yiding, boseant, mssarang
FB internal diff:
D1596118
Tasks:
4952724