Add a systrace support for lock contention logging.

- Now several ART executables like oatdump need to link with libcutils
  as the mutex code is shared among them.
- The blocking thread ID and lock owner thread ID are passed to
  ScopedContentionRecorder in the correct order.

Bug: 9986464
Change-Id: Id766de23fbc4af1d8ba2de051595e365b04f5ae7
diff --git a/build/Android.libarttest.mk b/build/Android.libarttest.mk
index 4fb2bbf..f7b4d1e 100644
--- a/build/Android.libarttest.mk
+++ b/build/Android.libarttest.mk
@@ -46,13 +46,14 @@
   ifeq ($$(art_target_or_host),target)
     LOCAL_CLANG := $(ART_TARGET_CLANG)
     LOCAL_CFLAGS := $(ART_TARGET_CFLAGS) $(ART_TARGET_DEBUG_CFLAGS)
-    LOCAL_SHARED_LIBRARIES += libdl
+    LOCAL_SHARED_LIBRARIES += libdl libcutils
     LOCAL_STATIC_LIBRARIES := libgtest
     LOCAL_MODULE_PATH := $(ART_TEST_OUT)
     include $(BUILD_SHARED_LIBRARY)
   else # host
     LOCAL_CLANG := $(ART_HOST_CLANG)
     LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+    LOCAL_STATIC_LIBRARIES := libcutils
     LOCAL_LDLIBS := -ldl -lpthread
     ifeq ($(HOST_OS),linux)
       LOCAL_LDLIBS += -lrt
diff --git a/dex2oat/Android.mk b/dex2oat/Android.mk
index 5cfab51..05dcd7b 100644
--- a/dex2oat/Android.mk
+++ b/dex2oat/Android.mk
@@ -22,10 +22,10 @@
 	dex2oat.cc
 
 ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
-  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libart-compiler,art/compiler,target,ndebug))
+  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug))
 endif
 ifeq ($(ART_BUILD_TARGET_DEBUG),true)
-  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libartd-compiler,art/compiler,target,debug))
+  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug))
 endif
 
 ifeq ($(WITH_HOST_DALVIK),true)
diff --git a/oatdump/Android.mk b/oatdump/Android.mk
index bf5c41b..a63b229 100644
--- a/oatdump/Android.mk
+++ b/oatdump/Android.mk
@@ -22,10 +22,10 @@
 include art/build/Android.executable.mk
 
 ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
-  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),,,target,ndebug))
+  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libcutils,,target,ndebug))
 endif
 ifeq ($(ART_BUILD_TARGET_DEBUG),true)
-  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),,,target,debug))
+  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libcutils,,target,debug))
 endif
 
 ifeq ($(WITH_HOST_DALVIK),true)
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index 7f3b459..a559d63 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -19,7 +19,10 @@
 
 #include "mutex.h"
 
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
 #include "cutils/atomic-inline.h"
+#include "cutils/trace.h"
 #include "runtime.h"
 #include "thread.h"
 
@@ -45,10 +48,16 @@
         blocked_tid_(kLogLockContentions ? blocked_tid : 0),
         owner_tid_(kLogLockContentions ? owner_tid : 0),
         start_nano_time_(kLogLockContentions ? NanoTime() : 0) {
+    if (kLogLockContentions) {
+      std::string msg = StringPrintf("Lock contention on %s (owner tid: %llu)",
+                                     mutex->GetName(), owner_tid);
+      ATRACE_BEGIN(msg.c_str());
+    }
   }
 
   ~ScopedContentionRecorder() {
     if (kLogLockContentions) {
+      ATRACE_END();
       uint64_t end_nano_time = NanoTime();
       mutex_->RecordContention(blocked_tid_, owner_tid_, end_nano_time - start_nano_time_);
     }
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 3007978..b99e7c9 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -351,7 +351,7 @@
         done = android_atomic_acquire_cas(0, 1, &state_) == 0;
       } else {
         // Failed to acquire, hang up.
-        ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
+        ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
         android_atomic_inc(&num_contenders_);
         if (futex(&state_, FUTEX_WAIT, 1, NULL, NULL, 0) != 0) {
           // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
@@ -554,7 +554,7 @@
       done = android_atomic_acquire_cas(0, -1, &state_) == 0;
     } else {
       // Failed to acquire, hang up.
-      ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
+      ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
       android_atomic_inc(&num_pending_writers_);
       if (futex(&state_, FUTEX_WAIT, cur_state, NULL, NULL, 0) != 0) {
         // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning.
@@ -623,7 +623,7 @@
       if (ComputeRelativeTimeSpec(&rel_ts, end_abs_ts, now_abs_ts)) {
         return false;  // Timed out.
       }
-      ScopedContentionRecorder scr(this, GetExclusiveOwnerTid(), SafeGetTid(self));
+      ScopedContentionRecorder scr(this, SafeGetTid(self), GetExclusiveOwnerTid());
       android_atomic_inc(&num_pending_writers_);
       if (futex(&state_, FUTEX_WAIT, cur_state, &rel_ts, NULL, 0) != 0) {
         if (errno == ETIMEDOUT) {