ART: Change contention logging lock strategy
Compute possible contention (wrt/ sampling) first. Then keep the whole
logging section under the mutator lock *and* the thread-list lock so
as to avoid any thread races.
This change is in preparation for heavier logging under heavy lock
contention.
Enable contention logging in 004-ThreadStress.
Bug: 62353392
Test: m test-art-host
Change-Id: I7b9126bae273f0cddb681f5f013ce6d814c7b8c0
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index a617818..4d309bf 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -401,31 +401,28 @@
if (original_owner_thread_id != 0u) {
// Woken from contention.
if (log_contention) {
- uint32_t original_owner_tid = 0;
- std::string original_owner_name;
- {
+ uint64_t wait_ms = MilliTime() - wait_start_ms;
+ uint32_t sample_percent;
+ if (wait_ms >= lock_profiling_threshold_) {
+ sample_percent = 100;
+ } else {
+ sample_percent = 100 * wait_ms / lock_profiling_threshold_;
+ }
+ if (sample_percent != 0 && (static_cast<uint32_t>(rand() % 100) < sample_percent)) {
+ // Reacquire mutator_lock_ for logging.
+ ScopedObjectAccess soa(self);
+ // Acquire thread-list lock to find thread and keep it from dying until we're done.
MutexLock mu2(Thread::Current(), *Locks::thread_list_lock_);
+
// Re-find the owner in case the thread got killed.
Thread* original_owner = Runtime::Current()->GetThreadList()->FindThreadByThreadId(
original_owner_thread_id);
- // Do not do any work that requires the mutator lock.
- if (original_owner != nullptr) {
- original_owner_tid = original_owner->GetTid();
- original_owner->GetThreadName(original_owner_name);
- }
- }
- if (original_owner_tid != 0u) {
- uint64_t wait_ms = MilliTime() - wait_start_ms;
- uint32_t sample_percent;
- if (wait_ms >= lock_profiling_threshold_) {
- sample_percent = 100;
- } else {
- sample_percent = 100 * wait_ms / lock_profiling_threshold_;
- }
- if (sample_percent != 0 && (static_cast<uint32_t>(rand() % 100) < sample_percent)) {
- // Reacquire mutator_lock_ for logging.
- ScopedObjectAccess soa(self);
+ if (original_owner != nullptr) {
+ pid_t original_owner_tid = original_owner->GetTid();
+ std::string original_owner_name;
+ original_owner->GetThreadName(original_owner_name);
+
if (wait_ms > kLongWaitMs && owners_method != nullptr) {
uint32_t pc;
ArtMethod* m = self->GetCurrentMethod(&pc);
diff --git a/runtime/monitor.h b/runtime/monitor.h
index 96c5a5b..752b2a0 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -228,7 +228,6 @@
ArtMethod* owners_method,
uint32_t owners_dex_pc,
size_t num_waiters)
- REQUIRES(!Locks::thread_list_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
// Wait on a monitor until timeout, interrupt, or notification. Used for Object.wait() and
diff --git a/test/004-ThreadStress/run b/test/004-ThreadStress/run
new file mode 100755
index 0000000..d2e7fae
--- /dev/null
+++ b/test/004-ThreadStress/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 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.
+
+# Enable lock contention logging.
+${RUN} --runtime-option -Xlockprofthreshold:10 "${@}"