Futex::futexWait returns FutexResult
authorYedidya Feldblum <yfeldblum@fb.com>
Wed, 10 Jan 2018 06:39:13 +0000 (22:39 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 10 Jan 2018 06:51:03 +0000 (22:51 -0800)
Summary: [Folly] `Futex::futexWait` returns `FutexResult`.

Reviewed By: nbronson

Differential Revision: D6673871

fbshipit-source-id: 378c69d8362970e985da31e31d8e9b0179d2917f

folly/detail/Futex.h
folly/detail/MemoryIdler.h
folly/test/FutexTest.cpp
folly/test/MemoryIdlerTest.cpp

index 1e72b15ce14289a87909947c9423b11a83ea1199..000bf1a62dcfad7ebfac2acdf1fc437307600498 100644 (file)
@@ -52,10 +52,10 @@ struct Futex : Atom<uint32_t>, boost::noncopyable {
   /** Puts the thread to sleep if this->load() == expected.  Returns true when
    *  it is returning because it has consumed a wake() event, false for any
    *  other return (signal, this->load() != expected, or spurious wakeup). */
-  bool futexWait(uint32_t expected, uint32_t waitMask = -1) {
+  FutexResult futexWait(uint32_t expected, uint32_t waitMask = -1) {
     auto rv = futexWaitImpl(expected, nullptr, nullptr, waitMask);
     assert(rv != FutexResult::TIMEDOUT);
-    return rv == FutexResult::AWOKEN;
+    return rv;
   }
 
   /** Similar to futexWait but also accepts a deadline until when the wait call
index 3c987cc9223340f93279e7d722283e5813912886..caac253e014be4bd99a749f74f51a90a85daa216 100644 (file)
@@ -102,7 +102,7 @@ struct MemoryIdler {
   template <
       template <typename> class Atom,
       typename Clock = std::chrono::steady_clock>
-  static bool futexWait(
+  static FutexResult futexWait(
       Futex<Atom>& fut,
       uint32_t expected,
       uint32_t waitMask = -1,
@@ -110,7 +110,6 @@ struct MemoryIdler {
           defaultIdleTimeout.load(std::memory_order_acquire),
       size_t stackToRetain = kDefaultStackToRetain,
       float timeoutVariationFrac = 0.5) {
-
     if (idleTimeout == Clock::duration::max()) {
       // no need to use futexWaitUntil if no timeout is possible
       return fut.futexWait(expected, waitMask);
@@ -128,7 +127,7 @@ struct MemoryIdler {
         // finished before timeout hit, no flush
         assert(rv == FutexResult::VALUE_CHANGED || rv == FutexResult::AWOKEN ||
                rv == FutexResult::INTERRUPTED);
-        return rv == FutexResult::AWOKEN;
+        return rv;
       }
     }
 
index 464c85240ae2a6693d4a4699c8bed7ccb7be3abd..7da35b713b680f0b2c8581504e8632cc4e773178 100644 (file)
@@ -39,14 +39,14 @@ typedef DeterministicSchedule DSched;
 template <template <typename> class Atom>
 void run_basic_thread(
     Futex<Atom>& f) {
-  EXPECT_TRUE(f.futexWait(0));
+  EXPECT_EQ(FutexResult::AWOKEN, f.futexWait(0));
 }
 
 template <template <typename> class Atom>
 void run_basic_tests() {
   Futex<Atom> f(0);
 
-  EXPECT_FALSE(f.futexWait(1));
+  EXPECT_EQ(FutexResult::VALUE_CHANGED, f.futexWait(1));
   EXPECT_EQ(f.futexWake(), 0);
 
   auto thr = DSched::thread(std::bind(run_basic_thread<Atom>, std::ref(f)));
@@ -191,7 +191,8 @@ void run_wake_blocked_test() {
   for (auto delay = std::chrono::milliseconds(1);; delay *= 2) {
     bool success = false;
     Futex<Atom> f(0);
-    auto thr = DSched::thread([&] { success = f.futexWait(0); });
+    auto thr = DSched::thread(
+        [&] { success = FutexResult::AWOKEN == f.futexWait(0); });
     /* sleep override */ std::this_thread::sleep_for(delay);
     f.store(1);
     f.futexWake(1);
index 538dbf0e97f0968d6462ffca2a6b161ebbd91f04..6945f22e87a4f360be7700b89c9383133fb3946e 100644 (file)
@@ -95,7 +95,7 @@ namespace folly { namespace detail {
 /// used type
 template <>
 struct Futex<MockAtom> {
-  MOCK_METHOD2(futexWait, bool(uint32_t, uint32_t));
+  MOCK_METHOD2(futexWait, FutexResult(uint32_t, uint32_t));
   MOCK_METHOD3(futexWaitUntil,
                FutexResult(uint32_t, const MockClock::time_point&, uint32_t));
 };
@@ -114,7 +114,9 @@ TEST(MemoryIdler, futexWaitValueChangedEarly) {
   EXPECT_CALL(fut, futexWaitUntil(1, AllOf(Ge(begin + idleTimeout),
                                            Lt(begin + 2 * idleTimeout)), -1))
       .WillOnce(Return(FutexResult::VALUE_CHANGED));
-  EXPECT_FALSE((MemoryIdler::futexWait<MockAtom, MockClock>(fut, 1)));
+  EXPECT_EQ(
+      FutexResult::VALUE_CHANGED,
+      (MemoryIdler::futexWait<MockAtom, MockClock>(fut, 1)));
 }
 
 TEST(MemoryIdler, futexWaitValueChangedLate) {
@@ -129,8 +131,10 @@ TEST(MemoryIdler, futexWaitValueChangedLate) {
                                            Lt(begin + 2 * idleTimeout)), -1))
       .WillOnce(Return(FutexResult::TIMEDOUT));
   EXPECT_CALL(fut, futexWait(1, -1))
-      .WillOnce(Return(false));
-  EXPECT_FALSE((MemoryIdler::futexWait<MockAtom, MockClock>(fut, 1)));
+      .WillOnce(Return(FutexResult::VALUE_CHANGED));
+  EXPECT_EQ(
+      FutexResult::VALUE_CHANGED,
+      (MemoryIdler::futexWait<MockAtom, MockClock>(fut, 1)));
 }
 
 TEST(MemoryIdler, futexWaitAwokenEarly) {
@@ -143,7 +147,9 @@ TEST(MemoryIdler, futexWaitAwokenEarly) {
       .WillOnce(Return(begin));
   EXPECT_CALL(fut, futexWaitUntil(1, Ge(begin + idleTimeout), -1))
       .WillOnce(Return(FutexResult::AWOKEN));
-  EXPECT_TRUE((MemoryIdler::futexWait<MockAtom, MockClock>(fut, 1)));
+  EXPECT_EQ(
+      FutexResult::AWOKEN,
+      (MemoryIdler::futexWait<MockAtom, MockClock>(fut, 1)));
 }
 
 TEST(MemoryIdler, futexWaitAwokenLate) {
@@ -156,28 +162,31 @@ TEST(MemoryIdler, futexWaitAwokenLate) {
       .WillOnce(Return(begin));
   EXPECT_CALL(fut, futexWaitUntil(1, begin + idleTimeout, -1))
       .WillOnce(Return(FutexResult::TIMEDOUT));
-  EXPECT_CALL(fut, futexWait(1, -1))
-      .WillOnce(Return(true));
-  EXPECT_TRUE((MemoryIdler::futexWait<MockAtom, MockClock>(
-      fut, 1, -1, idleTimeout, 100, 0.0f)));
+  EXPECT_CALL(fut, futexWait(1, -1)).WillOnce(Return(FutexResult::AWOKEN));
+  EXPECT_EQ(
+      FutexResult::AWOKEN,
+      (MemoryIdler::futexWait<MockAtom, MockClock>(
+          fut, 1, -1, idleTimeout, 100, 0.0f)));
 }
 
 TEST(MemoryIdler, futexWaitImmediateFlush) {
   StrictMock<Futex<MockAtom>> fut;
   auto clock = MockClock::setup();
 
-  EXPECT_CALL(fut, futexWait(2, 0xff))
-      .WillOnce(Return(true));
-  EXPECT_TRUE((MemoryIdler::futexWait<MockAtom, MockClock>(
-      fut, 2, 0xff, std::chrono::seconds(0))));
+  EXPECT_CALL(fut, futexWait(2, 0xff)).WillOnce(Return(FutexResult::AWOKEN));
+  EXPECT_EQ(
+      FutexResult::AWOKEN,
+      (MemoryIdler::futexWait<MockAtom, MockClock>(
+          fut, 2, 0xff, std::chrono::seconds(0))));
 }
 
 TEST(MemoryIdler, futexWaitNeverFlush) {
   StrictMock<Futex<MockAtom>> fut;
   auto clock = MockClock::setup();
 
-  EXPECT_CALL(fut, futexWait(1, -1))
-      .WillOnce(Return(true));
-  EXPECT_TRUE((MemoryIdler::futexWait<MockAtom, MockClock>(
-      fut, 1, -1, MockClock::duration::max())));
+  EXPECT_CALL(fut, futexWait(1, -1)).WillOnce(Return(FutexResult::AWOKEN));
+  EXPECT_EQ(
+      FutexResult::AWOKEN,
+      (MemoryIdler::futexWait<MockAtom, MockClock>(
+          fut, 1, -1, MockClock::duration::max())));
 }