Implement lock contention event logging.

Change-Id: I88b30985590157bb5d04229a97f191b898f141bb
diff --git a/src/monitor.cc b/src/monitor.cc
index aede4b8..b6f91bc 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -93,14 +93,25 @@
 #define LW_LOCK_COUNT_SHIFT 19
 #define LW_LOCK_COUNT(x) (((x) >> LW_LOCK_COUNT_SHIFT) & LW_LOCK_COUNT_MASK)
 
+bool (*Monitor::is_sensitive_thread_hook_)() = NULL;
 bool Monitor::is_verbose_ = false;
+uint32_t Monitor::lock_profiling_threshold_ = 0;
 
 bool Monitor::IsVerbose() {
   return is_verbose_;
 }
 
-void Monitor::SetVerbose(bool is_verbose) {
+bool Monitor::IsSensitiveThread() {
+  if (is_sensitive_thread_hook_ != NULL) {
+    return (*is_sensitive_thread_hook_)();
+  }
+  return false;
+}
+
+void Monitor::Init(bool is_verbose, uint32_t lock_profiling_threshold, bool (*is_sensitive_thread_hook)()) {
   is_verbose_ = is_verbose;
+  lock_profiling_threshold_ = lock_profiling_threshold;
+  is_sensitive_thread_hook_ = is_sensitive_thread_hook;
 }
 
 Monitor::Monitor(Object* obj)
@@ -182,158 +193,52 @@
   return obj_;
 }
 
-/*
-static char *logWriteInt(char *dst, int value) {
-  *dst++ = EVENT_TYPE_INT;
-  set4LE((uint8_t *)dst, value);
-  return dst + 4;
-}
-
-static char *logWriteString(char *dst, const char *value, size_t len) {
-  *dst++ = EVENT_TYPE_STRING;
-  len = len < 32 ? len : 32;
-  set4LE((uint8_t *)dst, len);
-  dst += 4;
-  memcpy(dst, value, len);
-  return dst + len;
-}
-
-#define EVENT_LOG_TAG_dvm_lock_sample 20003
-
-static void logContentionEvent(Thread *self, uint32_t waitMs, uint32_t samplePercent,
-                               const char *ownerFileName, uint32_t ownerLineNumber)
-{
-    const StackSaveArea *saveArea;
-    const Method *meth;
-    uint32_t relativePc;
-    char eventBuffer[174];
-    const char *fileName;
-    char procName[33];
-    char *cp;
-    size_t len;
-    int fd;
-
-    saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
-    meth = saveArea->method;
-    cp = eventBuffer;
-
-    // Emit the event list length, 1 byte.
-    *cp++ = 9;
-
-    // Emit the process name, <= 37 bytes.
-    fd = open("/proc/self/cmdline", O_RDONLY);
-    memset(procName, 0, sizeof(procName));
-    read(fd, procName, sizeof(procName) - 1);
-    close(fd);
-    len = strlen(procName);
-    cp = logWriteString(cp, procName, len);
-
-    // Emit the sensitive thread ("main thread") status, 5 bytes.
-    bool isSensitive = false;
-    if (gDvm.isSensitiveThreadHook != NULL) {
-        isSensitive = gDvm.isSensitiveThreadHook();
-    }
-    cp = logWriteInt(cp, isSensitive);
-
-    // Emit self thread name string, <= 37 bytes.
-    std::string selfName = dvmGetThreadName(self);
-    cp = logWriteString(cp, selfName.c_str(), selfName.size());
-
-    // Emit the wait time, 5 bytes.
-    cp = logWriteInt(cp, waitMs);
-
-    // Emit the source code file name, <= 37 bytes.
-    fileName = dvmGetMethodSourceFile(meth);
-    if (fileName == NULL) fileName = "";
-    cp = logWriteString(cp, fileName, strlen(fileName));
-
-    // Emit the source code line number, 5 bytes.
-    relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
-    cp = logWriteInt(cp, dvmLineNumFromPC(meth, relativePc));
-
-    // Emit the lock owner source code file name, <= 37 bytes.
-    if (ownerFileName == NULL) {
-        ownerFileName = "";
-    } else if (strcmp(fileName, ownerFileName) == 0) {
-        // Common case, so save on log space.
-        ownerFileName = "-";
-    }
-    cp = logWriteString(cp, ownerFileName, strlen(ownerFileName));
-
-    // Emit the source code line number, 5 bytes.
-    cp = logWriteInt(cp, ownerLineNumber);
-
-    // Emit the sample percentage, 5 bytes.
-    cp = logWriteInt(cp, samplePercent);
-
-    assert((size_t)(cp - eventBuffer) <= sizeof(eventBuffer));
-    android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample,
-                       EVENT_TYPE_LIST,
-                       eventBuffer,
-                       (size_t)(cp - eventBuffer));
-}
-*/
-
 void Monitor::Lock(Thread* self) {
-//  uint32_t waitThreshold, samplePercent;
-//  uint64_t waitStart, waitEnd, waitMs;
-
   if (owner_ == self) {
     lock_count_++;
     return;
   }
+
+  uint64_t waitStart, waitEnd;
   if (!lock_.TryLock()) {
+    uint32_t wait_threshold = lock_profiling_threshold_;
+    const char* current_owner_filename = NULL;
+    uint32_t current_owner_line_number = -1;
     {
       ScopedThreadStateChange tsc(self, Thread::kBlocked);
-//      waitThreshold = gDvm.lockProfThreshold;
-//      if (waitThreshold) {
-//        waitStart = dvmGetRelativeTimeUsec();
-//      }
-//      const char* currentOwnerFileName = mon->ownerFileName;
-//      uint32_t currentOwnerLineNumber = mon->ownerLineNumber;
+      if (wait_threshold != 0) {
+        waitStart = NanoTime() / 1000;
+      }
+      current_owner_filename = owner_filename_;
+      current_owner_line_number = owner_line_number_;
 
       lock_.Lock();
-//      if (waitThreshold) {
-//        waitEnd = dvmGetRelativeTimeUsec();
-//      }
+      if (wait_threshold != 0) {
+        waitEnd = NanoTime() / 1000;
+      }
     }
-//    if (waitThreshold) {
-//      waitMs = (waitEnd - waitStart) / 1000;
-//      if (waitMs >= waitThreshold) {
-//        samplePercent = 100;
-//      } else {
-//        samplePercent = 100 * waitMs / waitThreshold;
-//      }
-//      if (samplePercent != 0 && ((uint32_t)rand() % 100 < samplePercent)) {
-//        logContentionEvent(self, waitMs, samplePercent, currentOwnerFileName, currentOwnerLineNumber);
-//      }
-//    }
+
+    if (wait_threshold != 0) {
+      uint64_t wait_ms = (waitEnd - waitStart) / 1000;
+      uint32_t sample_percent;
+      if (wait_ms >= wait_threshold) {
+        sample_percent = 100;
+      } else {
+        sample_percent = 100 * wait_ms / wait_threshold;
+      }
+      if (sample_percent != 0 && (static_cast<uint32_t>(rand() % 100) < sample_percent)) {
+        LogContentionEvent(self, wait_ms, sample_percent, current_owner_filename, current_owner_line_number);
+      }
+    }
   }
   owner_ = self;
   DCHECK_EQ(lock_count_, 0);
 
   // When debugging, save the current monitor holder for future
   // acquisition failures to use in sampled logging.
-//  if (gDvm.lockProfThreshold > 0) {
-//    const StackSaveArea *saveArea;
-//    const Method *meth;
-//    mon->ownerLineNumber = 0;
-//    if (self->interpSave.curFrame == NULL) {
-//      mon->ownerFileName = "no_frame";
-//    } else if ((saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame)) == NULL) {
-//      mon->ownerFileName = "no_save_area";
-//    } else if ((meth = saveArea->method) == NULL) {
-//      mon->ownerFileName = "no_method";
-//    } else {
-//      uint32_t relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
-//      mon->ownerFileName = (char*) dvmGetMethodSourceFile(meth);
-//      if (mon->ownerFileName == NULL) {
-//        mon->ownerFileName = "no_method_file";
-//      } else {
-//        mon->ownerLineNumber = dvmLineNumFromPC(meth, relativePc);
-//      }
-//    }
-//  }
+  if (lock_profiling_threshold_ != 0) {
+    self->GetCurrentLocation(owner_filename_, owner_line_number_);
+  }
 }
 
 void ThrowIllegalMonitorStateException(const char* msg) {