Guard entrypoint changing by runtime shutdown lock.
There was a race when we changed the allocation entrypoints where a
new thread would be starting (Thread::Init) and initialize to the
wrong entrypoints. Guarding allocation entrypoint changing
with the runtime shutdown lock fixes this race condition since
Thread::Init is only called with the runtime shutdown lock held.
Bug: 13250963
Change-Id: I8eb209c124b6bf17020de874e1b0083f158b8200
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 7a2fab9..fd9dc4c 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -154,7 +154,6 @@
arch/arm/registers_arm.cc \
arch/x86/registers_x86.cc \
arch/mips/registers_mips.cc \
- arch/quick_alloc_entrypoints.cc \
entrypoints/entrypoint_utils.cc \
entrypoints/interpreter/interpreter_entrypoints.cc \
entrypoints/jni/jni_entrypoints.cc \
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index fc85ae3..23e3433 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -16,6 +16,7 @@
#include "entrypoints/interpreter/interpreter_entrypoints.h"
#include "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/math_entrypoints.h"
@@ -130,8 +131,6 @@
// Generic JNI downcall
extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
-extern void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
-
void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
PortableEntryPoints* ppoints, QuickEntryPoints* qpoints) {
// Interpreter
diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
index 41d79c2..500a2eb 100644
--- a/runtime/arch/mips/entrypoints_init_mips.cc
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -15,6 +15,7 @@
*/
#include "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/math_entrypoints.h"
diff --git a/runtime/arch/quick_alloc_entrypoints.cc b/runtime/arch/quick_alloc_entrypoints.cc
deleted file mode 100644
index 9363f81..0000000
--- a/runtime/arch/quick_alloc_entrypoints.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "gc/heap.h"
-
-#define GENERATE_ENTRYPOINTS(suffix) \
-extern "C" void* art_quick_alloc_array##suffix(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_alloc_array_resolved##suffix(void* klass, void*, int32_t); \
-extern "C" void* art_quick_alloc_array_with_access_check##suffix(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_alloc_object##suffix(uint32_t type_idx, void* method); \
-extern "C" void* art_quick_alloc_object_resolved##suffix(void* klass, void* method); \
-extern "C" void* art_quick_alloc_object_initialized##suffix(void* klass, void* method); \
-extern "C" void* art_quick_alloc_object_with_access_check##suffix(uint32_t type_idx, void* method); \
-extern "C" void* art_quick_check_and_alloc_array##suffix(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_alloc_array##suffix##_instrumented(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(void* klass, void*, int32_t); \
-extern "C" void* art_quick_alloc_array_with_access_check##suffix##_instrumented(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_alloc_object##suffix##_instrumented(uint32_t type_idx, void* method); \
-extern "C" void* art_quick_alloc_object_resolved##suffix##_instrumented(void* klass, void* method); \
-extern "C" void* art_quick_alloc_object_initialized##suffix##_instrumented(void* klass, void* method); \
-extern "C" void* art_quick_alloc_object_with_access_check##suffix##_instrumented(uint32_t type_idx, void* method); \
-extern "C" void* art_quick_check_and_alloc_array##suffix##_instrumented(uint32_t, void*, int32_t); \
-extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented(uint32_t, void*, int32_t); \
-void SetQuickAllocEntryPoints##suffix(QuickEntryPoints* qpoints, bool instrumented) { \
- if (instrumented) { \
- qpoints->pAllocArray = art_quick_alloc_array##suffix##_instrumented; \
- qpoints->pAllocArrayResolved = art_quick_alloc_array_resolved##suffix##_instrumented; \
- qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check##suffix##_instrumented; \
- qpoints->pAllocObject = art_quick_alloc_object##suffix##_instrumented; \
- qpoints->pAllocObjectResolved = art_quick_alloc_object_resolved##suffix##_instrumented; \
- qpoints->pAllocObjectInitialized = art_quick_alloc_object_initialized##suffix##_instrumented; \
- qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check##suffix##_instrumented; \
- qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array##suffix##_instrumented; \
- qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented; \
- } else { \
- qpoints->pAllocArray = art_quick_alloc_array##suffix; \
- qpoints->pAllocArrayResolved = art_quick_alloc_array_resolved##suffix; \
- qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check##suffix; \
- qpoints->pAllocObject = art_quick_alloc_object##suffix; \
- qpoints->pAllocObjectResolved = art_quick_alloc_object_resolved##suffix; \
- qpoints->pAllocObjectInitialized = art_quick_alloc_object_initialized##suffix; \
- qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check##suffix; \
- qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array##suffix; \
- qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check##suffix; \
- } \
-}
-
-namespace art {
-
-// Generate the entrypoint functions.
-GENERATE_ENTRYPOINTS(_dlmalloc);
-GENERATE_ENTRYPOINTS(_rosalloc);
-GENERATE_ENTRYPOINTS(_bump_pointer);
-GENERATE_ENTRYPOINTS(_tlab);
-
-static bool entry_points_instrumented = false;
-static gc::AllocatorType entry_points_allocator = gc::kAllocatorTypeDlMalloc;
-
-void SetQuickAllocEntryPointsAllocator(gc::AllocatorType allocator) {
- entry_points_allocator = allocator;
-}
-
-void SetQuickAllocEntryPointsInstrumented(bool instrumented) {
- entry_points_instrumented = instrumented;
-}
-
-void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints) {
- switch (entry_points_allocator) {
- case gc::kAllocatorTypeDlMalloc: {
- SetQuickAllocEntryPoints_dlmalloc(qpoints, entry_points_instrumented);
- break;
- }
- case gc::kAllocatorTypeRosAlloc: {
- SetQuickAllocEntryPoints_rosalloc(qpoints, entry_points_instrumented);
- break;
- }
- case gc::kAllocatorTypeBumpPointer: {
- CHECK(kMovingCollector);
- SetQuickAllocEntryPoints_bump_pointer(qpoints, entry_points_instrumented);
- break;
- }
- case gc::kAllocatorTypeTLAB: {
- CHECK(kMovingCollector);
- SetQuickAllocEntryPoints_tlab(qpoints, entry_points_instrumented);
- break;
- }
- default: {
- LOG(FATAL) << "Unimplemented";
- }
- }
-}
-
-} // namespace art
diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
index 763cbde..c4a7b1b 100644
--- a/runtime/arch/x86/entrypoints_init_x86.cc
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -15,6 +15,7 @@
*/
#include "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/entrypoint_utils.h"
diff --git a/runtime/arch/x86_64/entrypoints_init_x86_64.cc b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
index fe298c8..30067cf 100644
--- a/runtime/arch/x86_64/entrypoints_init_x86_64.cc
+++ b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
@@ -15,6 +15,7 @@
*/
#include "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/entrypoint_utils.h"
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index 2e1b69d..ccc0f3d 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
+
#include "callee_save_frame.h"
#include "entrypoints/entrypoint_utils.h"
#include "mirror/art_method-inl.h"
@@ -104,4 +106,90 @@
GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(BumpPointer, gc::kAllocatorTypeBumpPointer)
GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(TLAB, gc::kAllocatorTypeTLAB)
+#define GENERATE_ENTRYPOINTS(suffix) \
+extern "C" void* art_quick_alloc_array##suffix(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_alloc_array_resolved##suffix(void* klass, void*, int32_t); \
+extern "C" void* art_quick_alloc_array_with_access_check##suffix(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_alloc_object##suffix(uint32_t type_idx, void* method); \
+extern "C" void* art_quick_alloc_object_resolved##suffix(void* klass, void* method); \
+extern "C" void* art_quick_alloc_object_initialized##suffix(void* klass, void* method); \
+extern "C" void* art_quick_alloc_object_with_access_check##suffix(uint32_t type_idx, void* method); \
+extern "C" void* art_quick_check_and_alloc_array##suffix(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_alloc_array##suffix##_instrumented(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(void* klass, void*, int32_t); \
+extern "C" void* art_quick_alloc_array_with_access_check##suffix##_instrumented(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_alloc_object##suffix##_instrumented(uint32_t type_idx, void* method); \
+extern "C" void* art_quick_alloc_object_resolved##suffix##_instrumented(void* klass, void* method); \
+extern "C" void* art_quick_alloc_object_initialized##suffix##_instrumented(void* klass, void* method); \
+extern "C" void* art_quick_alloc_object_with_access_check##suffix##_instrumented(uint32_t type_idx, void* method); \
+extern "C" void* art_quick_check_and_alloc_array##suffix##_instrumented(uint32_t, void*, int32_t); \
+extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented(uint32_t, void*, int32_t); \
+void SetQuickAllocEntryPoints##suffix(QuickEntryPoints* qpoints, bool instrumented) { \
+ if (instrumented) { \
+ qpoints->pAllocArray = art_quick_alloc_array##suffix##_instrumented; \
+ qpoints->pAllocArrayResolved = art_quick_alloc_array_resolved##suffix##_instrumented; \
+ qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check##suffix##_instrumented; \
+ qpoints->pAllocObject = art_quick_alloc_object##suffix##_instrumented; \
+ qpoints->pAllocObjectResolved = art_quick_alloc_object_resolved##suffix##_instrumented; \
+ qpoints->pAllocObjectInitialized = art_quick_alloc_object_initialized##suffix##_instrumented; \
+ qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check##suffix##_instrumented; \
+ qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array##suffix##_instrumented; \
+ qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented; \
+ } else { \
+ qpoints->pAllocArray = art_quick_alloc_array##suffix; \
+ qpoints->pAllocArrayResolved = art_quick_alloc_array_resolved##suffix; \
+ qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check##suffix; \
+ qpoints->pAllocObject = art_quick_alloc_object##suffix; \
+ qpoints->pAllocObjectResolved = art_quick_alloc_object_resolved##suffix; \
+ qpoints->pAllocObjectInitialized = art_quick_alloc_object_initialized##suffix; \
+ qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check##suffix; \
+ qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array##suffix; \
+ qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check##suffix; \
+ } \
+}
+
+// Generate the entrypoint functions.
+GENERATE_ENTRYPOINTS(_dlmalloc);
+GENERATE_ENTRYPOINTS(_rosalloc);
+GENERATE_ENTRYPOINTS(_bump_pointer);
+GENERATE_ENTRYPOINTS(_tlab);
+
+static bool entry_points_instrumented = false;
+static gc::AllocatorType entry_points_allocator = gc::kAllocatorTypeDlMalloc;
+
+void SetQuickAllocEntryPointsAllocator(gc::AllocatorType allocator) {
+ entry_points_allocator = allocator;
+}
+
+void SetQuickAllocEntryPointsInstrumented(bool instrumented) {
+ entry_points_instrumented = instrumented;
+}
+
+void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints) {
+ switch (entry_points_allocator) {
+ case gc::kAllocatorTypeDlMalloc: {
+ SetQuickAllocEntryPoints_dlmalloc(qpoints, entry_points_instrumented);
+ break;
+ }
+ case gc::kAllocatorTypeRosAlloc: {
+ SetQuickAllocEntryPoints_rosalloc(qpoints, entry_points_instrumented);
+ break;
+ }
+ case gc::kAllocatorTypeBumpPointer: {
+ CHECK(kMovingCollector);
+ SetQuickAllocEntryPoints_bump_pointer(qpoints, entry_points_instrumented);
+ break;
+ }
+ case gc::kAllocatorTypeTLAB: {
+ CHECK(kMovingCollector);
+ SetQuickAllocEntryPoints_tlab(qpoints, entry_points_instrumented);
+ break;
+ }
+ default: {
+ LOG(FATAL) << "Unimplemented";
+ }
+ }
+}
+
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.h b/runtime/entrypoints/quick/quick_alloc_entrypoints.h
new file mode 100644
index 0000000..7fd3fe9
--- /dev/null
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ALLOC_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ALLOC_ENTRYPOINTS_H_
+
+#include "gc/heap.h"
+#include "quick_entrypoints.h"
+
+namespace art {
+
+namespace gc {
+enum AllocatorType;
+} // namespace gc
+
+void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
+
+// Runtime shutdown lock is necessary to prevent races in thread initialization. When the thread is
+// starting it doesn't hold the mutator lock until after it has been added to the thread list.
+// However, Thread::Init is guarded by the runtime shutdown lock, so we can prevent these races by
+// holding the runtime shutdown lock and the mutator lock when we update the entrypoints.
+
+void SetQuickAllocEntryPointsAllocator(gc::AllocatorType allocator)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::runtime_shutdown_lock_);
+
+void SetQuickAllocEntryPointsInstrumented(bool instrumented)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::runtime_shutdown_lock_);
+
+} // namespace art
+
+#endif // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ALLOC_ENTRYPOINTS_H_
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 9ad21cf..89601ff 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -45,6 +45,7 @@
#include "gc/space/rosalloc_space-inl.h"
#include "gc/space/space-inl.h"
#include "gc/space/zygote_space.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "heap-inl.h"
#include "image.h"
#include "invoke_arg_array_builder.h"
@@ -65,8 +66,6 @@
namespace art {
-extern void SetQuickAllocEntryPointsAllocator(gc::AllocatorType allocator);
-
namespace gc {
static constexpr bool kGCALotMode = false;
@@ -308,11 +307,12 @@
}
void Heap::ChangeAllocator(AllocatorType allocator) {
- // These two allocators are only used internally and don't have any entrypoints.
- DCHECK_NE(allocator, kAllocatorTypeLOS);
- DCHECK_NE(allocator, kAllocatorTypeNonMoving);
if (current_allocator_ != allocator) {
+ // These two allocators are only used internally and don't have any entrypoints.
+ CHECK_NE(allocator, kAllocatorTypeLOS);
+ CHECK_NE(allocator, kAllocatorTypeNonMoving);
current_allocator_ = allocator;
+ MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
SetQuickAllocEntryPointsAllocator(current_allocator_);
Runtime::Current()->GetInstrumentation()->ResetQuickAllocEntryPoints();
}
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index b194d8d..88adf81 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -197,13 +197,16 @@
void RegisterNativeFree(JNIEnv* env, int bytes);
// Change the allocator, updates entrypoints.
- void ChangeAllocator(AllocatorType allocator);
+ void ChangeAllocator(AllocatorType allocator)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
+ LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_);
// Transition the garbage collector during runtime, may copy objects from one space to another.
void TransitionCollector(CollectorType collector_type);
// Change the collector to be one of the possible options (MS, CMS, SS).
- void ChangeCollector(CollectorType collector_type);
+ void ChangeCollector(CollectorType collector_type)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
// The given reference is believed to be to an object in the Java heap, check the soundness of it.
// TODO: NO_THREAD_SAFETY_ANALYSIS since we call this everywhere and it is impossible to find a
@@ -465,7 +468,8 @@
// Revoke all the thread-local allocation stacks.
void RevokeAllThreadLocalAllocationStacks(Thread* self)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
+ LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_, Locks::thread_list_lock_);
// Mark all the objects in the allocation stack in the specified bitmap.
void MarkAllocStack(accounting::SpaceBitmap* bitmap1, accounting::SpaceBitmap* bitmap2,
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 01ad46d..e10d881 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -23,6 +23,7 @@
#include "class_linker.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "interpreter/interpreter.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
@@ -41,8 +42,6 @@
namespace art {
-extern void SetQuickAllocEntryPointsInstrumented(bool instrumented);
-
namespace instrumentation {
const bool kVerboseInstrumentation = false;
@@ -466,10 +465,13 @@
quick_alloc_entry_points_instrumentation_counter_.FetchAndAdd(1) == 0;
if (enable_instrumentation) {
// Instrumentation wasn't enabled so enable it.
- SetQuickAllocEntryPointsInstrumented(true);
ThreadList* tl = Runtime::Current()->GetThreadList();
tl->SuspendAll();
- ResetQuickAllocEntryPoints();
+ {
+ MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
+ SetQuickAllocEntryPointsInstrumented(true);
+ ResetQuickAllocEntryPoints();
+ }
tl->ResumeAll();
}
}
@@ -481,10 +483,13 @@
const bool disable_instrumentation =
quick_alloc_entry_points_instrumentation_counter_.FetchAndSub(1) == 1;
if (disable_instrumentation) {
- SetQuickAllocEntryPointsInstrumented(false);
ThreadList* tl = Runtime::Current()->GetThreadList();
tl->SuspendAll();
- ResetQuickAllocEntryPoints();
+ {
+ MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
+ SetQuickAllocEntryPointsInstrumented(false);
+ ResetQuickAllocEntryPoints();
+ }
tl->ResumeAll();
}
}
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 017573a..d7a0b4d 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -167,9 +167,11 @@
return interpreter_handler_table_;
}
- void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
- void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
- void ResetQuickAllocEntryPoints();
+ void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_,
+ Locks::runtime_shutdown_lock_);
+ void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_,
+ Locks::runtime_shutdown_lock_);
+ void ResetQuickAllocEntryPoints() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
// Update the code of a method respecting any installed stubs.
void UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 3862ae2..f843ae5 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -40,6 +40,7 @@
#include "debugger.h"
#include "dex_file-inl.h"
#include "entrypoints/entrypoint_utils.h"
+#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "gc_map.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
@@ -109,8 +110,6 @@
&quick_entrypoints_);
}
-void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints);
-
void Thread::ResetQuickAllocEntryPointsForThread() {
ResetQuickAllocEntryPoints(&quick_entrypoints_);
}