| /* |
| * 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(reinterpret_cast<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(reinterpret_cast<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->GetThreadName(thread_name); |
| 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. |
| uintptr_t pc; |
| AbstractMethod* m = self->GetCurrentMethod(&pc); |
| const char* filename; |
| uint32_t line_number; |
| TranslateLocation(m, pc, 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 |