diff options
| -rw-r--r-- | runtime/gc/collector/mark_sweep.cc | 29 | ||||
| -rw-r--r-- | runtime/gc/collector/mark_sweep.h | 4 | ||||
| -rw-r--r-- | runtime/thread_list.cc | 33 | ||||
| -rw-r--r-- | runtime/thread_list.h | 4 |
4 files changed, 44 insertions, 26 deletions
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 894ceba216..ac5931fa53 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -444,27 +444,8 @@ class MarkSweepMarkObjectSlowPath { } PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL); MemMap::DumpMaps(LOG(INTERNAL_FATAL), true); - { - LOG(INTERNAL_FATAL) << "Attempting see if it's a bad root"; - Thread* self = Thread::Current(); - if (Locks::mutator_lock_->IsExclusiveHeld(self)) { - mark_sweep_->VerifyRoots(); - } else { - const bool heap_bitmap_exclusive_locked = - Locks::heap_bitmap_lock_->IsExclusiveHeld(self); - if (heap_bitmap_exclusive_locked) { - Locks::heap_bitmap_lock_->ExclusiveUnlock(self); - } - { - ScopedThreadSuspension(self, kSuspended); - ScopedSuspendAll ssa(__FUNCTION__); - mark_sweep_->VerifyRoots(); - } - if (heap_bitmap_exclusive_locked) { - Locks::heap_bitmap_lock_->ExclusiveLock(self); - } - } - } + LOG(INTERNAL_FATAL) << "Attempting see if it's a bad thread root\n"; + mark_sweep_->VerifySuspendedThreadRoots(); LOG(FATAL) << "Can't mark invalid object"; } } @@ -591,15 +572,15 @@ class VerifyRootVisitor : public SingleRootVisitor { if (heap->GetLiveBitmap()->GetContinuousSpaceBitmap(root) == nullptr) { space::LargeObjectSpace* large_object_space = heap->GetLargeObjectsSpace(); if (large_object_space != nullptr && !large_object_space->Contains(root)) { - LOG(INTERNAL_FATAL) << "Found invalid root: " << root << " " << info; + LOG(INTERNAL_FATAL) << "Found invalid root: " << root << " " << info << "\n"; } } } }; -void MarkSweep::VerifyRoots() { +void MarkSweep::VerifySuspendedThreadRoots() { VerifyRootVisitor visitor; - Runtime::Current()->GetThreadList()->VisitRoots(&visitor); + Runtime::Current()->GetThreadList()->VisitRootsForSuspendedThreads(&visitor); } void MarkSweep::MarkRoots(Thread* self) { diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h index c19107a626..7168f96940 100644 --- a/runtime/gc/collector/mark_sweep.h +++ b/runtime/gc/collector/mark_sweep.h @@ -250,8 +250,8 @@ class MarkSweep : public GarbageCollector { // Verify the roots of the heap and print out information related to any invalid roots. // Called in MarkObject, so may we may not hold the mutator lock. - void VerifyRoots() - NO_THREAD_SAFETY_ANALYSIS; + void VerifySuspendedThreadRoots() + SHARED_REQUIRES(Locks::mutator_lock_); // Expand mark stack to 2x its current size. void ExpandMarkStack() diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 80b99fcd02..d90bd8d26b 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -1300,6 +1300,39 @@ void ThreadList::ForEach(void (*callback)(Thread*, void*), void* context) { } } +void ThreadList::VisitRootsForSuspendedThreads(RootVisitor* visitor) { + Thread* const self = Thread::Current(); + std::vector<Thread*> threads_to_visit; + + // Tell threads to suspend and copy them into list. + { + MutexLock mu(self, *Locks::thread_list_lock_); + MutexLock mu2(self, *Locks::thread_suspend_count_lock_); + for (Thread* thread : list_) { + thread->ModifySuspendCount(self, +1, nullptr, false); + if (thread == self || thread->IsSuspended()) { + threads_to_visit.push_back(thread); + } else { + thread->ModifySuspendCount(self, -1, nullptr, false); + } + } + } + + // Visit roots without holding thread_list_lock_ and thread_suspend_count_lock_ to prevent lock + // order violations. + for (Thread* thread : threads_to_visit) { + thread->VisitRoots(visitor); + } + + // Restore suspend counts. + { + MutexLock mu2(self, *Locks::thread_suspend_count_lock_); + for (Thread* thread : threads_to_visit) { + thread->ModifySuspendCount(self, -1, nullptr, false); + } + } +} + void ThreadList::VisitRoots(RootVisitor* visitor) const { MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); for (const auto& thread : list_) { diff --git a/runtime/thread_list.h b/runtime/thread_list.h index df81ad1a7b..49f65e16a7 100644 --- a/runtime/thread_list.h +++ b/runtime/thread_list.h @@ -144,6 +144,10 @@ class ThreadList { void VisitRoots(RootVisitor* visitor) const SHARED_REQUIRES(Locks::mutator_lock_); + void VisitRootsForSuspendedThreads(RootVisitor* visitor) + REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_) + SHARED_REQUIRES(Locks::mutator_lock_); + // Return a copy of the thread list. std::list<Thread*> GetList() REQUIRES(Locks::thread_list_lock_) { return list_; |