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 "${@}"