[heap] Fix global safepoint when waiting in event loop

When starting a global safepoint, it could happen that one isolate is
waiting/blocking in the event loop, which prevents this isolate from
reaching a safepoint. As a consequence we therefore deadlock when
performing the safepoint. We can solve this by simply posting a task
for each isolate that when run performs a safepoint check.

This CL also renames IncludeMainThreadUnlessInitiator to
ShouldIncludeMainThread.

Bug: v8:11708, v8:12645
Change-Id: Ide956b3c39b350c2bb0279a7dd94ff79cb9d771b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3555771
Reviewed-by: Anton Bikineev <bikineev@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79675}
This commit is contained in:
Dominik Inführ 2022-03-29 14:06:10 +02:00 committed by V8 LUCI CQ
parent 007076e536
commit 3eb8671edb
3 changed files with 30 additions and 9 deletions

View File

@ -84,18 +84,43 @@ void IsolateSafepoint::TryInitiateGlobalSafepointScope(
InitiateGlobalSafepointScopeRaw(initiator, client_data);
}
class GlobalSafepointInterruptTask : public CancelableTask {
public:
explicit GlobalSafepointInterruptTask(Heap* heap)
: CancelableTask(heap->isolate()), heap_(heap) {}
~GlobalSafepointInterruptTask() override = default;
GlobalSafepointInterruptTask(const GlobalSafepointInterruptTask&) = delete;
GlobalSafepointInterruptTask& operator=(const GlobalSafepointInterruptTask&) =
delete;
private:
// v8::internal::CancelableTask overrides.
void RunInternal() override { heap_->main_thread_local_heap()->Safepoint(); }
Heap* heap_;
};
void IsolateSafepoint::InitiateGlobalSafepointScopeRaw(
Isolate* initiator, PerClientSafepointData* client_data) {
CHECK_EQ(++active_safepoint_scopes_, 1);
barrier_.Arm();
size_t running =
SetSafepointRequestedFlags(IncludeMainThreadUnlessInitiator(initiator));
SetSafepointRequestedFlags(ShouldIncludeMainThread(initiator));
client_data->set_locked_and_running(running);
if (isolate() != initiator) {
// An isolate might be waiting in the event loop. Post a task in order to
// wake it up.
V8::GetCurrentPlatform()
->GetForegroundTaskRunner(reinterpret_cast<v8::Isolate*>(isolate()))
->PostTask(std::make_unique<GlobalSafepointInterruptTask>(heap_));
}
}
IsolateSafepoint::IncludeMainThread
IsolateSafepoint::IncludeMainThreadUnlessInitiator(Isolate* initiator) {
IsolateSafepoint::IncludeMainThread IsolateSafepoint::ShouldIncludeMainThread(
Isolate* initiator) {
const bool is_initiator = isolate() == initiator;
return is_initiator ? IncludeMainThread::kNo : IncludeMainThread::kYes;
}
@ -136,7 +161,7 @@ void IsolateSafepoint::LockMutex(LocalHeap* local_heap) {
void IsolateSafepoint::LeaveGlobalSafepointScope(Isolate* initiator) {
local_heaps_mutex_.AssertHeld();
CHECK_EQ(--active_safepoint_scopes_, 0);
ClearSafepointRequestedFlags(IncludeMainThreadUnlessInitiator(initiator));
ClearSafepointRequestedFlags(ShouldIncludeMainThread(initiator));
barrier_.Disarm();
local_heaps_mutex_.Unlock();
}

View File

@ -94,7 +94,7 @@ class IsolateSafepoint final {
void WaitUntilRunningThreadsInSafepoint(
const PerClientSafepointData* client_data);
IncludeMainThread IncludeMainThreadUnlessInitiator(Isolate* initiator);
IncludeMainThread ShouldIncludeMainThread(Isolate* initiator);
void LockMutex(LocalHeap* local_heap);

View File

@ -273,10 +273,6 @@
# TODO(v8:10915): Fails with --future.
'harmony/weakrefs/stress-finalizationregistry-dirty-enqueue': [SKIP],
# BUG(v8:12645)
'shared-memory/shared-struct-workers': [SKIP],
'shared-memory/shared-struct-atomics-workers': [SKIP],
# Needs deterministic test helpers for concurrent maglev tiering.
# TODO(jgruber,v8:7700): Implement ASAP.
'maglev/18': [SKIP],