| Index: systrace/atrace_helper/jni/process_info.cc
|
| diff --git a/systrace/atrace_helper/jni/process_info.cc b/systrace/atrace_helper/jni/process_info.cc
|
| index 172217bf6536509045593eb3a9ae9c0c2114d7dc..b5c66a8417923e9da4ebfc2684348d7e205d7af0 100644
|
| --- a/systrace/atrace_helper/jni/process_info.cc
|
| +++ b/systrace/atrace_helper/jni/process_info.cc
|
| @@ -13,90 +13,179 @@
|
| #include "file_utils.h"
|
| #include "logging.h"
|
|
|
| -ProcessInfo::ProcessInfo(int pid) : memory_(pid), pid_(pid) {}
|
| +using file_utils::ForEachPidInProcPath;
|
| +using file_utils::ReadProcFile;
|
| +using file_utils::ReadProcFileTrimmed;
|
|
|
| -bool ProcessInfo::IsProcess(int pid) {
|
| - char buf[256];
|
| - ssize_t rsize = file_utils::ReadProcFile(pid, "status", buf, sizeof(buf));
|
| +
|
| +namespace {
|
| +
|
| +const char kAppExe[] = "/system/bin/app_process";
|
| +const char kZygote[] = "zygote";
|
| +
|
| +std::string ReadProcString(int pid, const char* path) {
|
| + char buf[512];
|
| + if (!file_utils::ReadProcFileTrimmed(pid, path, buf, sizeof(buf)))
|
| + return "";
|
| + return buf;
|
| +}
|
| +
|
| +int ReadTgid(int pid) {
|
| + char buf[512];
|
| + ssize_t rsize = ReadProcFile(pid, "status", buf, sizeof(buf));
|
| if (rsize <= 0)
|
| - return false;
|
| + return -1;
|
| const char kTgid[] = "\nTgid:";
|
| const char* tgid_line = strstr(buf, kTgid);
|
| - CHECK(tgid_line);
|
| - int tgid = 0;
|
| + if (!tgid_line)
|
| + return -1;
|
| + int tgid = -1;
|
| if (sscanf(tgid_line + strlen(kTgid), "%d", &tgid) != 1)
|
| - CHECK(false);
|
| - return tgid == pid;
|
| + return -1;
|
| + return tgid;
|
| }
|
|
|
| -bool ProcessInfo::ReadProcessName() {
|
| - if (!file_utils::ReadProcFileTrimmed(pid_, "cmdline", name_, sizeof(name_)))
|
| - return false;
|
| -
|
| - // Fallback on "comm" for kernel threads.
|
| - if (strlen(name_) == 0) {
|
| - if (!file_utils::ReadProcFileTrimmed(pid_, "comm", name_, sizeof(name_)))
|
| - return false;
|
| - }
|
| -
|
| - // Get also the exe path, to distinguish system vs java apps and bitness.
|
| +std::string ReadExe(int pid) {
|
| + char exe[PATH_MAX];
|
| char exe_path[64];
|
| - sprintf(exe_path, "/proc/%d/exe", pid_);
|
| - exe_[0] = '\0';
|
| - ssize_t res = readlink(exe_path, exe_, sizeof(exe_) - 1);
|
| + sprintf(exe_path, "/proc/%d/exe", pid);
|
| + exe[0] = '\0';
|
| + ssize_t res = readlink(exe_path, exe, sizeof(exe) - 1);
|
| if (res >= 0)
|
| - exe_[res] = '\0';
|
| -
|
| - return true;
|
| + exe[res] = '\0';
|
| + return exe;
|
| }
|
|
|
| -bool ProcessInfo::ReadThreadNames() {
|
| - char tasks_path[64];
|
| - sprintf(tasks_path, "/proc/%d/task", pid_);
|
| - CHECK(threads_.empty());
|
| - ThreadInfoMap* threads = &threads_;
|
| - const int pid = pid_;
|
| - file_utils::ForEachPidInProcPath(tasks_path, [pid, threads](int tid) {
|
| - char comm[64];
|
| - std::unique_ptr<ThreadInfo> thread_info(new ThreadInfo());
|
| - sprintf(comm, "task/%d/comm", tid);
|
| - if (!file_utils::ReadProcFileTrimmed(pid, comm, thread_info->name,
|
| - sizeof(thread_info->name))) {
|
| - return;
|
| - }
|
| - (*threads)[tid] = std::move(thread_info);
|
| - });
|
| +bool ReadOomStats(int pid, InstantProcessInfo::ProcessSnapshot* snapshot) {
|
| + char buf[64];
|
| + if (ReadProcFileTrimmed(pid, "oom_score", buf, sizeof(buf)))
|
| + snapshot->oom_score = atoi(buf);
|
| + else
|
| + return false;
|
| + if (ReadProcFileTrimmed(pid, "oom_score_adj", buf, sizeof(buf)))
|
| + snapshot->oom_score_adj = atoi(buf);
|
| + else
|
| + return false;
|
| return true;
|
| }
|
|
|
| -bool ProcessInfo::ReadOOMStats() {
|
| +bool ReadPageFaultsAndCpuTimeStats(
|
| + int pid, InstantProcessInfo::ProcessSnapshot* snapshot) {
|
| +
|
| char buf[512];
|
| - if (file_utils::ReadProcFileTrimmed(pid_, "oom_adj", buf, sizeof(buf)))
|
| - oom_adj_ = atoi(buf);
|
| - else
|
| + if (!ReadProcFileTrimmed(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;
|
| +}
|
|
|
| - if (file_utils::ReadProcFileTrimmed(pid_, "oom_score", buf, sizeof(buf)))
|
| - oom_score_ = atoi(buf);
|
| - else
|
| - return false;
|
| +} // namespace
|
|
|
| - if (file_utils::ReadProcFileTrimmed(pid_, "oom_score_adj", buf, sizeof(buf)))
|
| - oom_score_adj_ = atoi(buf);
|
| - else
|
| - return false;
|
| +
|
| +bool PersistentProcessInfo::UpdateProcessInfo(int pid) {
|
| + ProcessInfo* process;
|
| + bool first_update = false;
|
| +
|
| + if (!processes_.count(pid)) {
|
| + if (ReadTgid(pid) != pid)
|
| + return false;
|
| + process = new ProcessInfo();
|
| + processes_[pid] = std::unique_ptr<ProcessInfo>(process);
|
| + first_update = true;
|
| + } else {
|
| + process = processes_[pid].get();
|
| + }
|
| +
|
| + // Get process name.
|
| + if (first_update) {
|
| + process->pid = pid;
|
| + process->name = ReadProcString(pid, "cmdline");
|
| + if (process->name.empty()) {
|
| + process->in_kernel = true;
|
| + process->name = ReadProcString(pid, "comm");
|
| + } else {
|
| + process->in_kernel = false;
|
| + process->exe = ReadExe(pid);
|
| + }
|
| + }
|
| +
|
| + // Detect apps.
|
| + process->is_app = !process->in_kernel &&
|
| + !strncmp(process->exe.c_str(), kAppExe, sizeof(kAppExe) - 1) &&
|
| + strncmp(process->name.c_str(), kZygote, sizeof(kZygote) - 1);
|
| +
|
| + // Get thread names.
|
| + if (!process->in_kernel) {
|
| + char tasks_path[64];
|
| + sprintf(tasks_path, "/proc/%d/task", pid);
|
| + ForEachPidInProcPath(tasks_path, [process, pid](int tid) {
|
| + if (process->threads.count(tid))
|
| + return;
|
| + ThreadInfo* thread = new ThreadInfo();
|
| + process->threads[tid] = std::unique_ptr<ThreadInfo>(thread);
|
| +
|
| + char task_comm[64];
|
| + sprintf(task_comm, "task/%d/comm", tid);
|
| + thread->tid = tid;
|
| + thread->name = ReadProcString(pid, task_comm);
|
| + if (process->is_app && thread->name.empty())
|
| + thread->name = "UI Thread";
|
| + });
|
| + }
|
|
|
| return true;
|
| }
|
|
|
| -bool ProcessInfo::ReadPageFaultsAndCPUTimeStats() {
|
| - char buf[512];
|
| - if (!file_utils::ReadProcFileTrimmed(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 %*ld %*ld %*ld %*ld %*ld %*ld %llu",
|
| - &minflt_, &majflt_, &utime_, &stime_, &start_time_);
|
| - CHECK(ret == 5);
|
| +void ProcessDumpManager::SetFullDumpPredicate(const DumpPredicate& predicate) {
|
| + full_dump_predicate_ =
|
| + std::unique_ptr<DumpPredicate>(new DumpPredicate(predicate));
|
| +}
|
| +
|
| +void ProcessDumpManager::SetGraphicsDumpPredicate(
|
| + const DumpPredicate& predicate) {
|
| + graphics_dump_predicate_ =
|
| + std::unique_ptr<DumpPredicate>(new DumpPredicate(predicate));
|
| +}
|
| +
|
| +bool ProcessDumpManager::TakeSnapshot() {
|
| + global_snapshot_.processes_.clear();
|
| + global_snapshot_.timestamp_ = GetTimestamp();
|
| +
|
| + ForEachPidInProcPath("/proc", [this](int pid) {
|
| + if (!persistent_.UpdateProcessInfo(pid))
|
| + return;
|
| +
|
| + const PersistentProcessInfo::ProcessInfo* process =
|
| + persistent_.processes_[pid].get();
|
| +
|
| + // Snapshot can't be obtained for kernel workers.
|
| + if (process->in_kernel)
|
| + return;
|
| +
|
| + InstantProcessInfo::ProcessSnapshot* process_snapshot =
|
| + new InstantProcessInfo::ProcessSnapshot();
|
| + global_snapshot_.processes_[pid] =
|
| + std::unique_ptr<InstantProcessInfo::ProcessSnapshot>(process_snapshot);
|
| + process_snapshot->pid = pid;
|
| +
|
| + ReadOomStats(pid, process_snapshot);
|
| + ReadPageFaultsAndCpuTimeStats(pid, process_snapshot);
|
| +
|
| + if (full_dump_predicate_ &&
|
| + (*full_dump_predicate_.get())(process)) {
|
| + process_snapshot->memory.ReadFullStats(pid);
|
| + } else {
|
| + process_snapshot->memory.ReadLightStats(pid);
|
| + }
|
| +
|
| + if (graphics_dump_predicate_ &&
|
| + (*graphics_dump_predicate_.get())(process)) {
|
| + process_snapshot->memory.ReadGpuStats(pid);
|
| + }
|
| + });
|
| return true;
|
| }
|
|
|