[SAB] Fix flake in Atomics.wait, part II

Refs: https://ci.chromium.org/buildbot/client.v8/V8%20Linux64%20TSAN/21047

Bug: v8:7836
Change-Id: Ic825065de419bbab97972d9b7a2beb6527b0a48a
Reviewed-on: https://chromium-review.googlesource.com/1103560
Commit-Queue: Ben Smith <binji@chromium.org>
Reviewed-by: Ben Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53810}
This commit is contained in:
Anna Henningsen 2018-06-19 00:23:30 +02:00 committed by Commit Bot
parent 71892ad96c
commit e980d0e860
2 changed files with 25 additions and 4 deletions

View File

@ -74,7 +74,14 @@ void FutexWaitList::RemoveNode(FutexWaitListNode* node) {
}
void AtomicsWaitWakeHandle::Wake() {
stopped_ = true;
// Adding a separate `NotifyWake()` variant that doesn't acquire the lock
// itself would likely just add unnecessary complexity..
// The split lock by itself isnt an issue, as long as the caller properly
// synchronizes this with the closing `AtomicsWaitCallback`.
{
base::LockGuard<base::Mutex> lock_guard(FutexEmulation::mutex_.Pointer());
stopped_ = true;
}
isolate_->futex_wait_list_node()->NotifyWake();
}
@ -126,6 +133,9 @@ Object* FutexEmulation::Wait(Isolate* isolate,
do { // Not really a loop, just makes it easier to break out early.
base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
// Reset node->waiting_ = false when leaving this scope (but while
// still holding the lock).
ResetWaitingOnScopeExit reset_waiting(node);
if (*p != value) {
result = isolate->heap()->not_equal();
@ -214,8 +224,6 @@ Object* FutexEmulation::Wait(Isolate* isolate,
wait_list_.Pointer()->RemoveNode(node);
} while (0);
node->waiting_ = false;
isolate->RunAtomicsWaitCallback(callback_result, array_buffer, addr, value,
rel_timeout_ms, nullptr);

View File

@ -62,6 +62,7 @@ class FutexWaitListNode {
private:
friend class FutexEmulation;
friend class FutexWaitList;
friend class ResetWaitingOnScopeExit;
base::ConditionVariable cond_;
// prev_ and next_ are protected by FutexEmulation::mutex_.
@ -70,7 +71,8 @@ class FutexWaitListNode {
void* backing_store_;
size_t wait_addr_;
// waiting_ and interrupted_ are protected by FutexEmulation::mutex_
// if this node is currently contained in FutexEmulation::wait_list_.
// if this node is currently contained in FutexEmulation::wait_list_
// or an AtomicsWaitWakeHandle has access to it.
bool waiting_;
bool interrupted_;
@ -94,6 +96,16 @@ class FutexWaitList {
DISALLOW_COPY_AND_ASSIGN(FutexWaitList);
};
class ResetWaitingOnScopeExit {
public:
explicit ResetWaitingOnScopeExit(FutexWaitListNode* node) : node_(node) {}
~ResetWaitingOnScopeExit() { node_->waiting_ = false; }
private:
FutexWaitListNode* node_;
DISALLOW_COPY_AND_ASSIGN(ResetWaitingOnScopeExit);
};
class FutexEmulation : public AllStatic {
public:
@ -124,6 +136,7 @@ class FutexEmulation : public AllStatic {
private:
friend class FutexWaitListNode;
friend class AtomicsWaitWakeHandle;
// `mutex_` protects the composition of `wait_list_` (i.e. no elements may be
// added or removed without holding this mutex), as well as the `waiting_`