Index: systrace/atrace_helper/jni/procfs_utils.cc |
diff --git a/systrace/atrace_helper/jni/procfs_utils.cc b/systrace/atrace_helper/jni/procfs_utils.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f14abe7e70beba731979369ff6053a7621589c71 |
--- /dev/null |
+++ b/systrace/atrace_helper/jni/procfs_utils.cc |
@@ -0,0 +1,117 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "procfs_utils.h" |
+ |
+#include <stdio.h> |
+#include <string.h> |
+ |
+#include "file_utils.h" |
+#include "logging.h" |
+ |
+using file_utils::ForEachPidInProcPath; |
+using file_utils::ReadProcFile; |
+using file_utils::ReadProcFileTrimmed; |
+ |
+namespace procfs_utils { |
+ |
+namespace { |
+ |
+const char kJavaAppPrefix[] = "/system/bin/app_process"; |
+const char kZygotePrefix[] = "zygote"; |
+ |
+inline void ReadProcString(int pid, const char* path, char* buf, size_t size) { |
+ if (!file_utils::ReadProcFileTrimmed(pid, path, buf, size)) |
+ buf[0] = '\0'; |
+} |
+ |
+inline void ReadExePath(int pid, char* buf, size_t size) { |
+ char exe_path[64]; |
+ sprintf(exe_path, "/proc/%d/exe", pid); |
+ ssize_t res = readlink(exe_path, buf, size - 1); |
+ if (res >= 0) |
+ buf[res] = '\0'; |
+ else |
+ buf[0] = '\0'; |
+} |
+ |
+inline bool IsApp(const char* name, const char* exe) { |
+ return strncmp(exe, kJavaAppPrefix, sizeof(kJavaAppPrefix) - 1) == 0 && |
+ strncmp(name, kZygotePrefix, sizeof(kZygotePrefix) - 1) != 0; |
+} |
+ |
+} // namespace |
+ |
+int ReadTgid(int pid) { |
+ static const char kTgid[] = "\nTgid:"; |
+ char buf[512]; |
+ ssize_t rsize = ReadProcFile(pid, "status", buf, sizeof(buf)); |
+ if (rsize <= 0) |
+ return -1; |
+ const char* tgid_line = strstr(buf, kTgid); |
+ CHECK(tgid_line); |
+ return atoi(tgid_line + sizeof(kTgid) - 1); |
+} |
+ |
+std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid) { |
+ ProcessInfo* process = new ProcessInfo(); |
+ process->pid = pid; |
+ ReadProcString(pid, "cmdline", process->name, sizeof(process->name)); |
+ if (process->name[0] != 0) { |
+ ReadExePath(pid, process->exe, sizeof(process->exe)); |
+ process->is_app = IsApp(process->name, process->exe); |
+ } else { |
+ ReadProcString(pid, "comm", process->name, sizeof(process->name)); |
+ CHECK(process->name[0]); |
+ process->in_kernel = true; |
+ } |
+ return std::unique_ptr<ProcessInfo>(process); |
+} |
+ |
+void ReadProcessThreads(ProcessInfo* process) { |
+ if (process->in_kernel) |
+ return; |
+ |
+ char tasks_path[64]; |
+ sprintf(tasks_path, "/proc/%d/task", process->pid); |
+ ForEachPidInProcPath(tasks_path, [process](int tid) { |
+ if (process->threads.count(tid)) |
+ return; |
+ ThreadInfo thread = { tid, "" }; |
+ char task_comm[64]; |
+ sprintf(task_comm, "task/%d/comm", tid); |
+ ReadProcString(process->pid, task_comm, thread.name, sizeof(thread.name)); |
+ if (thread.name[0] == '\0' && process->is_app) |
+ strcpy(thread.name, "UI Thread"); |
+ process->threads[tid] = thread; |
+ }); |
+} |
+ |
+bool ReadOomStats(ProcessSnapshot* snapshot) { |
+ char buf[64]; |
+ if (ReadProcFileTrimmed(snapshot->pid, "oom_score", buf, sizeof(buf))) |
+ snapshot->oom_score = atoi(buf); |
+ else |
+ return false; |
+ if (ReadProcFileTrimmed(snapshot->pid, "oom_score_adj", buf, sizeof(buf))) |
+ snapshot->oom_score_adj = atoi(buf); |
+ else |
+ return false; |
+ return true; |
+} |
+ |
+bool ReadPageFaultsAndCpuTimeStats(ProcessSnapshot* snapshot) { |
+ char buf[512]; |
+ if (!ReadProcFileTrimmed(snapshot->pid, "stat", buf, sizeof(buf))) |
+ return false; |
+ int ret = sscanf(buf, |
+ "%*d (%*[^)]) %*c %*d %*d %*d %*d %*d %*u %lu %*lu %lu %*lu %lu %lu", |
+ &snapshot->minor_faults, &snapshot->major_faults, |
+ &snapshot->utime, &snapshot->stime); |
+ CHECK(ret == 4); |
+ return true; |
+} |
+ |
+ |
+} // namespace procfs_utils |