From eab7000df62b7b8b2b114fb2a9b75b744506242c Mon Sep 17 00:00:00 2001 From: Maged Michael Date: Thu, 16 Feb 2017 12:19:29 -0800 Subject: [PATCH] Fix data race in Futex Summary: Fixed a data race between an atomic store by the waker and a nonatomic memcpy by the waiter. Reviewed By: nbronson Differential Revision: D4572410 fbshipit-source-id: 3982ca433e0f628636916516e35aeb7738ae030f --- folly/detail/Futex.cpp | 20 ++++++++++++-------- folly/test/FutexTest.cpp | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/folly/detail/Futex.cpp b/folly/detail/Futex.cpp index 118eb466..fa628602 100644 --- a/folly/detail/Futex.cpp +++ b/folly/detail/Futex.cpp @@ -226,21 +226,25 @@ int emulatedFutexWake(void* addr, int count, uint32_t waitMask) { return numAwoken; } +template FutexResult emulatedFutexWaitImpl( - void* addr, - uint32_t expected, - time_point* absSystemTime, - time_point* absSteadyTime, - uint32_t waitMask) { + F* futex, + uint32_t expected, + time_point* absSystemTime, + time_point* absSteadyTime, + uint32_t waitMask) { + static_assert( + std::is_same>::value || + std::is_same>::value, + "Type F must be either Futex or Futex"); + void* addr = static_cast(futex); auto& bucket = EmulatedFutexBucket::bucketFor(addr); EmulatedFutexWaitNode node(addr, waitMask); { std::unique_lock bucketLock(bucket.mutex_); - uint32_t actual; - memcpy(&actual, addr, sizeof(uint32_t)); - if (actual != expected) { + if (futex->load(std::memory_order_relaxed) != expected) { return FutexResult::VALUE_CHANGED; } diff --git a/folly/test/FutexTest.cpp b/folly/test/FutexTest.cpp index 689c51a4..24cd1756 100644 --- a/folly/test/FutexTest.cpp +++ b/folly/test/FutexTest.cpp @@ -182,6 +182,21 @@ void run_steady_clock_test() { EXPECT_TRUE(A <= B && B <= C); } +template