2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <linux/futex.h>
24 #include <sys/syscall.h>
26 #include <boost/noncopyable.hpp>
28 namespace folly { namespace detail {
31 * Futex is an atomic 32 bit unsigned integer that provides access to the
32 * futex() syscall on that value. It is templated in such a way that it
33 * can interact properly with DeterministicSchedule testing.
35 * If you don't know how to use futex(), you probably shouldn't be using
36 * this class. Even if you do know how, you should have a good reason
37 * (and benchmarks to back you up).
39 template <template <typename> class Atom = std::atomic>
40 struct Futex : Atom<uint32_t>, boost::noncopyable {
42 explicit Futex(uint32_t init = 0) : Atom<uint32_t>(init) {}
44 /** Puts the thread to sleep if this->load() == expected. Returns true when
45 * it is returning because it has consumed a wake() event, false for any
46 * other return (signal, this->load() != expected, or spurious wakeup). */
47 bool futexWait(uint32_t expected, uint32_t waitMask = -1);
49 /** Wakens up to count waiters where (waitMask & wakeMask) != 0,
50 * returning the number of awoken threads. */
51 int futexWake(int count = std::numeric_limits<int>::max(),
52 uint32_t wakeMask = -1);
56 inline bool Futex<std::atomic>::futexWait(uint32_t expected,
58 assert(sizeof(*this) == sizeof(int));
59 int rv = syscall(SYS_futex,
61 FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, /* op */
63 nullptr, /* timeout */
66 assert(rv == 0 || (errno == EWOULDBLOCK || errno == EINTR));
71 inline int Futex<std::atomic>::futexWake(int count, uint32_t wakeMask) {
72 assert(sizeof(*this) == sizeof(int));
73 int rv = syscall(SYS_futex,
75 FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, /* op */
77 nullptr, /* timeout */