Commit 5a913587 authored by Jeremy Roman's avatar Jeremy Roman Committed by Commit Bot

Use a non-recursive mutex for ProcessHeap::CrossThreadPersistentMutex.

This may enable us to remove support for recursive mutexes in the near
future.

Bugs in this CL are likely to manifest as threads hanging while
trying to acquire this mutex recursively (while manipulating GC objects).

Bug: 856641
Change-Id: Icfc3982f7489fb53ddd4df319c405002ee1c3ea8
Reviewed-on: https://chromium-review.googlesource.com/1112197Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570884}
parent c0100180
...@@ -459,8 +459,6 @@ void ThreadHeap::PromptlyFreed(size_t gc_info_index) { ...@@ -459,8 +459,6 @@ void ThreadHeap::PromptlyFreed(size_t gc_info_index) {
#if defined(ADDRESS_SANITIZER) #if defined(ADDRESS_SANITIZER)
void ThreadHeap::PoisonAllHeaps() { void ThreadHeap::PoisonAllHeaps() {
RecursiveMutexLocker persistent_lock(
ProcessHeap::CrossThreadPersistentMutex());
// Poisoning all unmarked objects in the other arenas. // Poisoning all unmarked objects in the other arenas.
for (int i = 1; i < BlinkGC::kNumberOfArenas; i++) for (int i = 1; i < BlinkGC::kNumberOfArenas; i++)
arenas_[i]->PoisonArena(); arenas_[i]->PoisonArena();
...@@ -472,8 +470,6 @@ void ThreadHeap::PoisonAllHeaps() { ...@@ -472,8 +470,6 @@ void ThreadHeap::PoisonAllHeaps() {
} }
void ThreadHeap::PoisonEagerArena() { void ThreadHeap::PoisonEagerArena() {
RecursiveMutexLocker persistent_lock(
ProcessHeap::CrossThreadPersistentMutex());
arenas_[BlinkGC::kEagerSweepArenaIndex]->PoisonArena(); arenas_[BlinkGC::kEagerSweepArenaIndex]->PoisonArena();
// CrossThreadPersistents in unmarked objects may be accessed from other // CrossThreadPersistents in unmarked objects may be accessed from other
// threads (e.g. in CrossThreadPersistentRegion::shouldTracePersistent) and // threads (e.g. in CrossThreadPersistentRegion::shouldTracePersistent) and
......
...@@ -365,8 +365,7 @@ class TestGCMarkingScope : public TestGCCollectGarbageScope { ...@@ -365,8 +365,7 @@ class TestGCMarkingScope : public TestGCCollectGarbageScope {
public: public:
explicit TestGCMarkingScope(BlinkGC::StackState state) explicit TestGCMarkingScope(BlinkGC::StackState state)
: TestGCCollectGarbageScope(state), : TestGCCollectGarbageScope(state),
atomic_pause_scope_(ThreadState::Current()), atomic_pause_scope_(ThreadState::Current()) {
persistent_lock_(ProcessHeap::CrossThreadPersistentMutex()) {
ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted( ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted(
BlinkGC::GCReason::kTesting); BlinkGC::GCReason::kTesting);
ThreadState::Current()->AtomicPausePrologue(state, BlinkGC::kAtomicMarking, ThreadState::Current()->AtomicPausePrologue(state, BlinkGC::kAtomicMarking,
...@@ -380,7 +379,6 @@ class TestGCMarkingScope : public TestGCCollectGarbageScope { ...@@ -380,7 +379,6 @@ class TestGCMarkingScope : public TestGCCollectGarbageScope {
private: private:
ThreadState::AtomicPauseScope atomic_pause_scope_; ThreadState::AtomicPauseScope atomic_pause_scope_;
RecursiveMutexLocker persistent_lock_;
}; };
class TestGCScope : public TestGCMarkingScope { class TestGCScope : public TestGCMarkingScope {
......
...@@ -175,6 +175,22 @@ class PersistentBase { ...@@ -175,6 +175,22 @@ class PersistentBase {
return this; return this;
} }
NO_SANITIZE_ADDRESS
void ClearWithLockHeld() {
static_assert(
crossThreadnessConfiguration == kCrossThreadPersistentConfiguration,
"This Persistent does not require the cross-thread lock.");
#if DCHECK_IS_ON()
DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
#endif
raw_ = nullptr;
CrossThreadPersistentRegion& region =
weaknessConfiguration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion();
region.FreePersistentNode(persistent_node_);
}
protected: protected:
NO_SANITIZE_ADDRESS NO_SANITIZE_ADDRESS
T* AtomicGet() { T* AtomicGet() {
...@@ -186,8 +202,7 @@ class PersistentBase { ...@@ -186,8 +202,7 @@ class PersistentBase {
NO_SANITIZE_ADDRESS NO_SANITIZE_ADDRESS
void Assign(T* ptr) { void Assign(T* ptr) {
if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) {
RecursiveMutexLocker persistent_lock( MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
ProcessHeap::CrossThreadPersistentMutex());
raw_ = ptr; raw_ = ptr;
} else { } else {
raw_ = ptr; raw_ = ptr;
...@@ -227,6 +242,7 @@ class PersistentBase { ...@@ -227,6 +242,7 @@ class PersistentBase {
weaknessConfiguration == kWeakPersistentConfiguration weaknessConfiguration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion() ? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion(); : ProcessHeap::GetCrossThreadPersistentRegion();
MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
region.AllocatePersistentNode(persistent_node_, this, trace_callback); region.AllocatePersistentNode(persistent_node_, this, trace_callback);
return; return;
} }
...@@ -250,6 +266,7 @@ class PersistentBase { ...@@ -250,6 +266,7 @@ class PersistentBase {
weaknessConfiguration == kWeakPersistentConfiguration weaknessConfiguration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion() ? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion(); : ProcessHeap::GetCrossThreadPersistentRegion();
MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
region.FreePersistentNode(persistent_node_); region.FreePersistentNode(persistent_node_);
} }
return; return;
...@@ -312,7 +329,29 @@ class PersistentBase { ...@@ -312,7 +329,29 @@ class PersistentBase {
Base* persistent = reinterpret_cast<Base*>(persistent_pointer); Base* persistent = reinterpret_cast<Base*>(persistent_pointer);
T* object = persistent->Get(); T* object = persistent->Get();
if (object && !ObjectAliveTrait<T>::IsHeapObjectAlive(object)) if (object && !ObjectAliveTrait<T>::IsHeapObjectAlive(object))
persistent->Clear(); ClearWeakPersistent(persistent);
}
static void ClearWeakPersistent(
PersistentBase<std::remove_const_t<T>,
kWeakPersistentConfiguration,
kCrossThreadPersistentConfiguration>* persistent) {
#if DCHECK_IS_ON()
DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
#endif
persistent->ClearWithLockHeld();
}
static void ClearWeakPersistent(
PersistentBase<std::remove_const_t<T>,
kWeakPersistentConfiguration,
kSingleThreadPersistentConfiguration>* persistent) {
persistent->Clear();
}
template <typename BadPersistent>
static void ClearWeakPersistent(BadPersistent* non_weak_persistent) {
NOTREACHED();
} }
// m_raw is accessed most, so put it at the first field. // m_raw is accessed most, so put it at the first field.
...@@ -852,8 +891,6 @@ template <typename T> ...@@ -852,8 +891,6 @@ template <typename T>
struct BindUnwrapTraits<blink::CrossThreadWeakPersistent<T>> { struct BindUnwrapTraits<blink::CrossThreadWeakPersistent<T>> {
static blink::CrossThreadPersistent<T> Unwrap( static blink::CrossThreadPersistent<T> Unwrap(
const blink::CrossThreadWeakPersistent<T>& wrapped) { const blink::CrossThreadWeakPersistent<T>& wrapped) {
WTF::RecursiveMutexLocker persistent_lock(
blink::ProcessHeap::CrossThreadPersistentMutex());
return blink::CrossThreadPersistent<T>(wrapped.Get()); return blink::CrossThreadPersistent<T>(wrapped.Get());
} }
}; };
......
...@@ -167,7 +167,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination( ...@@ -167,7 +167,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
// For heaps belonging to a thread that's detaching, any cross-thread // For heaps belonging to a thread that's detaching, any cross-thread
// persistents pointing into them needs to be disabled. Do that by clearing // persistents pointing into them needs to be disabled. Do that by clearing
// out the underlying heap reference. // out the underlying heap reference.
RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
PersistentNodeSlots* slots = persistent_region_.slots_; PersistentNodeSlots* slots = persistent_region_.slots_;
while (slots) { while (slots) {
...@@ -187,7 +187,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination( ...@@ -187,7 +187,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
BasePage* page = PageFromObject(raw_object); BasePage* page = PageFromObject(raw_object);
DCHECK(page); DCHECK(page);
if (page->Arena()->GetThreadState() == thread_state) { if (page->Arena()->GetThreadState() == thread_state) {
persistent->Clear(); persistent->ClearWithLockHeld();
DCHECK(slots->slot_[i].IsUnused()); DCHECK(slots->slot_[i].IsUnused());
} }
} }
...@@ -197,7 +197,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination( ...@@ -197,7 +197,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
#if defined(ADDRESS_SANITIZER) #if defined(ADDRESS_SANITIZER)
void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() { void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() {
RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
int persistent_count = 0; int persistent_count = 0;
for (PersistentNodeSlots* slots = persistent_region_.slots_; slots; for (PersistentNodeSlots* slots = persistent_region_.slots_; slots;
slots = slots->next_) { slots = slots->next_) {
......
...@@ -165,6 +165,7 @@ class PLATFORM_EXPORT PersistentRegion final { ...@@ -165,6 +165,7 @@ class PLATFORM_EXPORT PersistentRegion final {
#endif #endif
}; };
// Protected by ProcessHeap::CrossThreadPersistentMutex.
class CrossThreadPersistentRegion final { class CrossThreadPersistentRegion final {
USING_FAST_MALLOC(CrossThreadPersistentRegion); USING_FAST_MALLOC(CrossThreadPersistentRegion);
...@@ -172,14 +173,18 @@ class CrossThreadPersistentRegion final { ...@@ -172,14 +173,18 @@ class CrossThreadPersistentRegion final {
void AllocatePersistentNode(PersistentNode*& persistent_node, void AllocatePersistentNode(PersistentNode*& persistent_node,
void* self, void* self,
TraceCallback trace) { TraceCallback trace) {
RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); #if DCHECK_IS_ON()
DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
#endif
PersistentNode* node = PersistentNode* node =
persistent_region_.AllocatePersistentNode(self, trace); persistent_region_.AllocatePersistentNode(self, trace);
ReleaseStore(reinterpret_cast<void* volatile*>(&persistent_node), node); ReleaseStore(reinterpret_cast<void* volatile*>(&persistent_node), node);
} }
void FreePersistentNode(PersistentNode*& persistent_node) { void FreePersistentNode(PersistentNode*& persistent_node) {
RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); #if DCHECK_IS_ON()
DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
#endif
// When the thread that holds the heap object that the cross-thread // When the thread that holds the heap object that the cross-thread
// persistent shuts down, prepareForThreadStateTermination() will clear out // persistent shuts down, prepareForThreadStateTermination() will clear out
// the associated CrossThreadPersistent<> and PersistentNode so as to avoid // the associated CrossThreadPersistent<> and PersistentNode so as to avoid
......
...@@ -54,8 +54,8 @@ CrossThreadPersistentRegion& ProcessHeap::GetCrossThreadWeakPersistentRegion() { ...@@ -54,8 +54,8 @@ CrossThreadPersistentRegion& ProcessHeap::GetCrossThreadWeakPersistentRegion() {
return persistent_region; return persistent_region;
} }
RecursiveMutex& ProcessHeap::CrossThreadPersistentMutex() { Mutex& ProcessHeap::CrossThreadPersistentMutex() {
DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, ()); DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
return mutex; return mutex;
} }
......
...@@ -32,12 +32,7 @@ class PLATFORM_EXPORT ProcessHeap { ...@@ -32,12 +32,7 @@ class PLATFORM_EXPORT ProcessHeap {
// - Iteration and processing of weak cross-thread Persistents. The lock // - Iteration and processing of weak cross-thread Persistents. The lock
// needs to span both operations as iteration of weak persistents only // needs to span both operations as iteration of weak persistents only
// registers memory regions that are then processed afterwards. // registers memory regions that are then processed afterwards.
// static Mutex& CrossThreadPersistentMutex();
// Recursive as PrepareForThreadStateTermination() clears a PersistentNode's
// associated Persistent<> -- it in turn freeing the PersistentNode. And both
// CrossThreadPersistentRegion operations need a lock on the region before
// mutating.
static RecursiveMutex& CrossThreadPersistentMutex();
static void IncreaseTotalAllocatedObjectSize(size_t delta) { static void IncreaseTotalAllocatedObjectSize(size_t delta) {
AtomicAdd(&total_allocated_object_size_, static_cast<long>(delta)); AtomicAdd(&total_allocated_object_size_, static_cast<long>(delta));
......
...@@ -362,8 +362,7 @@ void ThreadState::VisitPersistents(Visitor* visitor) { ...@@ -362,8 +362,7 @@ void ThreadState::VisitPersistents(Visitor* visitor) {
Heap().stats_collector(), Heap().stats_collector(),
ThreadHeapStatsCollector::kVisitCrossThreadPersistents); ThreadHeapStatsCollector::kVisitCrossThreadPersistents);
// See ProcessHeap::CrossThreadPersistentMutex(). // See ProcessHeap::CrossThreadPersistentMutex().
RecursiveMutexLocker persistent_lock( MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
ProcessHeap::CrossThreadPersistentMutex());
ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor); ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor);
} }
{ {
...@@ -1706,8 +1705,7 @@ void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) { ...@@ -1706,8 +1705,7 @@ void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) {
{ {
// See ProcessHeap::CrossThreadPersistentMutex(). // See ProcessHeap::CrossThreadPersistentMutex().
RecursiveMutexLocker persistent_lock( MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
ProcessHeap::CrossThreadPersistentMutex());
VisitWeakPersistents(visitor); VisitWeakPersistents(visitor);
Heap().WeakProcessing(visitor); Heap().WeakProcessing(visitor);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment