Implement lock contention event logging.
Change-Id: I88b30985590157bb5d04229a97f191b898f141bb
diff --git a/src/monitor_android.cc b/src/monitor_android.cc
new file mode 100644
index 0000000..95dd397
--- /dev/null
+++ b/src/monitor_android.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 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 "monitor.h"
+#include "object.h"
+#include "thread.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "cutils/log.h"
+
+#define EVENT_LOG_TAG_dvm_lock_sample 20003
+
+namespace art {
+
+static void Set4LE(uint8_t* buf, uint32_t val) {
+ *buf++ = (uint8_t)(val);
+ *buf++ = (uint8_t)(val >> 8);
+ *buf++ = (uint8_t)(val >> 16);
+ *buf = (uint8_t)(val >> 24);
+}
+
+static char* EventLogWriteInt(char* dst, int value) {
+ *dst++ = EVENT_TYPE_INT;
+ Set4LE((uint8_t*) dst, value);
+ return dst + 4;
+}
+
+static char* EventLogWriteString(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;
+}
+
+void Monitor::LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, const char* owner_filename, uint32_t owner_line_number) {
+ // Emit the event list length, 1 byte.
+ char eventBuffer[174];
+ char* cp = eventBuffer;
+ *cp++ = 9;
+
+ // Emit the process name, <= 37 bytes.
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ char procName[33];
+ memset(procName, 0, sizeof(procName));
+ read(fd, procName, sizeof(procName) - 1);
+ close(fd);
+ size_t len = strlen(procName);
+ cp = EventLogWriteString(cp, procName, len);
+
+ // Emit the sensitive thread ("main thread") status, 5 bytes.
+ cp = EventLogWriteInt(cp, Monitor::IsSensitiveThread());
+
+ // Emit self thread name string, <= 37 bytes.
+ std::string thread_name(self->GetName()->ToModifiedUtf8());
+ cp = EventLogWriteString(cp, thread_name.c_str(), thread_name.size());
+
+ // Emit the wait time, 5 bytes.
+ cp = EventLogWriteInt(cp, wait_ms);
+
+ // Emit the source code file name, <= 37 bytes.
+ const char* filename;
+ uint32_t line_number;
+ self->GetCurrentLocation(filename, line_number);
+ cp = EventLogWriteString(cp, filename, strlen(filename));
+
+ // Emit the source code line number, 5 bytes.
+ cp = EventLogWriteInt(cp, line_number);
+
+ // Emit the lock owner source code file name, <= 37 bytes.
+ if (owner_filename == NULL) {
+ owner_filename = "";
+ } else if (strcmp(filename, owner_filename) == 0) {
+ // Common case, so save on log space.
+ owner_filename = "-";
+ }
+ cp = EventLogWriteString(cp, owner_filename, strlen(owner_filename));
+
+ // Emit the source code line number, 5 bytes.
+ cp = EventLogWriteInt(cp, owner_line_number);
+
+ // Emit the sample percentage, 5 bytes.
+ cp = EventLogWriteInt(cp, sample_percent);
+
+ CHECK_LE((size_t)(cp - eventBuffer), sizeof(eventBuffer));
+ android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample, EVENT_TYPE_LIST, eventBuffer, (size_t)(cp - eventBuffer));
+}
+
+} // namespace art