From 1cd53dbb2163f18b689d2a65cf9c6bdcdb01b407 Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Fri, 28 Mar 2014 15:26:48 -0700 Subject: Fix a DCHECK failure when causing GC from DDMS. Bug: 13647069 Change-Id: Iae2746b2b7b4493fcf5f0d40d2bf36a9b2d2efc8 --- runtime/gc/space/rosalloc_space.cc | 52 ++++++++++++++++++++++++++------------ runtime/gc/space/rosalloc_space.h | 6 ++++- 2 files changed, 41 insertions(+), 17 deletions(-) (limited to 'runtime/gc') diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc index 3c65205..012267b 100644 --- a/runtime/gc/space/rosalloc_space.cc +++ b/runtime/gc/space/rosalloc_space.cc @@ -231,7 +231,7 @@ size_t RosAllocSpace::Trim() { if (!rosalloc_->DoesReleaseAllPages()) { VLOG(heap) << "RosAllocSpace::Trim() "; size_t reclaimed = 0; - InspectAllRosAlloc(DlmallocMadviseCallback, &reclaimed); + InspectAllRosAlloc(DlmallocMadviseCallback, &reclaimed, false); return reclaimed; } return 0; @@ -239,8 +239,7 @@ size_t RosAllocSpace::Trim() { void RosAllocSpace::Walk(void(*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), void* arg) { - InspectAllRosAlloc(callback, arg); - callback(NULL, NULL, 0, arg); // Indicate end of a space. + InspectAllRosAlloc(callback, arg, true); } size_t RosAllocSpace::GetFootprint() { @@ -268,35 +267,56 @@ void RosAllocSpace::SetFootprintLimit(size_t new_size) { uint64_t RosAllocSpace::GetBytesAllocated() { size_t bytes_allocated = 0; - InspectAllRosAlloc(art::gc::allocator::RosAlloc::BytesAllocatedCallback, &bytes_allocated); + InspectAllRosAlloc(art::gc::allocator::RosAlloc::BytesAllocatedCallback, &bytes_allocated, false); return bytes_allocated; } uint64_t RosAllocSpace::GetObjectsAllocated() { size_t objects_allocated = 0; - InspectAllRosAlloc(art::gc::allocator::RosAlloc::ObjectsAllocatedCallback, &objects_allocated); + InspectAllRosAlloc(art::gc::allocator::RosAlloc::ObjectsAllocatedCallback, &objects_allocated, false); return objects_allocated; } +void RosAllocSpace::InspectAllRosAllocWithSuspendAll( + void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), + void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS { + // TODO: NO_THREAD_SAFETY_ANALYSIS. + Thread* self = Thread::Current(); + ThreadList* tl = Runtime::Current()->GetThreadList(); + tl->SuspendAll(); + { + MutexLock mu(self, *Locks::runtime_shutdown_lock_); + MutexLock mu2(self, *Locks::thread_list_lock_); + rosalloc_->InspectAll(callback, arg); + if (do_null_callback_at_end) { + callback(NULL, NULL, 0, arg); // Indicate end of a space. + } + } + tl->ResumeAll(); +} + void RosAllocSpace::InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), - void* arg) NO_THREAD_SAFETY_ANALYSIS { + void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS { // TODO: NO_THREAD_SAFETY_ANALYSIS. Thread* self = Thread::Current(); if (Locks::mutator_lock_->IsExclusiveHeld(self)) { // The mutators are already suspended. For example, a call path // from SignalCatcher::HandleSigQuit(). rosalloc_->InspectAll(callback, arg); - } else { - // The mutators are not suspended yet. - DCHECK(!Locks::mutator_lock_->IsSharedHeld(self)); - ThreadList* tl = Runtime::Current()->GetThreadList(); - tl->SuspendAll(); - { - MutexLock mu(self, *Locks::runtime_shutdown_lock_); - MutexLock mu2(self, *Locks::thread_list_lock_); - rosalloc_->InspectAll(callback, arg); + if (do_null_callback_at_end) { + callback(NULL, NULL, 0, arg); // Indicate end of a space. } - tl->ResumeAll(); + } else if (Locks::mutator_lock_->IsSharedHeld(self)) { + // The mutators are not suspended yet and we have a shared access + // to the mutator lock. Temporarily release the shared access by + // transitioning to the suspend state, and suspend the mutators. + self->TransitionFromRunnableToSuspended(kSuspended); + InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end); + self->TransitionFromSuspendedToRunnable(); + Locks::mutator_lock_->AssertSharedHeld(self); + } else { + // The mutators are not suspended yet. Suspend the mutators. + InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end); } } diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h index 949ec08..900e7a9 100644 --- a/runtime/gc/space/rosalloc_space.h +++ b/runtime/gc/space/rosalloc_space.h @@ -124,7 +124,11 @@ class RosAllocSpace : public MallocSpace { size_t maximum_size, bool low_memory_mode); void InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), - void* arg) + void* arg, bool do_null_callback_at_end) + LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_, Locks::thread_list_lock_); + void InspectAllRosAllocWithSuspendAll( + void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), + void* arg, bool do_null_callback_at_end) LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_, Locks::thread_list_lock_); // Underlying rosalloc. -- cgit v1.1