1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/process_info_snapshot.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <sys/sysctl.h>
872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sstream>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/sys_info.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Default constructor.
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessInfoSnapshot::ProcessInfoSnapshot() { }
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Destructor: just call |Reset()| to release everything.
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessInfoSnapshot::~ProcessInfoSnapshot() {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Reset();
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst size_t ProcessInfoSnapshot::kMaxPidListSize = 1000;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool GetKInfoForProcessID(pid_t pid, kinfo_proc* kinfo) {
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t len = sizeof(*kinfo);
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (sysctl(mib, arraysize(mib), kinfo, &len, NULL, 0) != 0) {
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    PLOG(ERROR) << "sysctl() for KERN_PROC";
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (len == 0) {
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // If the process isn't found then sysctl returns a length of 0.
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool GetExecutableNameForProcessID(
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    pid_t pid,
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string* executable_name) {
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!executable_name) {
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static int s_arg_max = 0;
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (s_arg_max == 0) {
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int mib[] = {CTL_KERN, KERN_ARGMAX};
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    size_t size = sizeof(s_arg_max);
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (sysctl(mib, arraysize(mib), &s_arg_max, &size, NULL, 0) != 0)
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      PLOG(ERROR) << "sysctl() for KERN_ARGMAX";
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (s_arg_max == 0)
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int mib[] = {CTL_KERN, KERN_PROCARGS, pid};
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t size = s_arg_max;
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  executable_name->resize(s_arg_max + 1);
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (sysctl(mib, arraysize(mib), &(*executable_name)[0],
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen             &size, NULL, 0) != 0) {
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Don't log the error since it's normal for this to fail.
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // KERN_PROCARGS returns multiple NULL terminated strings. Truncate
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // executable_name to just the first string.
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t end_pos = executable_name->find('\0');
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (end_pos == std::string::npos) {
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  executable_name->resize(end_pos);
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Converts a byte unit such as 'K' or 'M' into the scale for the unit.
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The scale can then be used to calculate the number of bytes in a value.
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The units are based on humanize_number(). See:
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// http://www.opensource.apple.com/source/libutil/libutil-21/humanize_number.c
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool ConvertByteUnitToScale(char unit, uint64_t* out_scale) {
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int shift = 0;
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  switch (unit) {
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'B':
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 0;
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'K':
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'k':
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 1;
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'M':
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 2;
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'G':
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 3;
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'T':
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 4;
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'P':
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 5;
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 'E':
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      shift = 6;
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    default:
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  uint64_t scale = 1;
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (int i = 0; i < shift; i++)
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scale *= 1024;
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  *out_scale = scale;
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Capture the information by calling '/bin/ps'.
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Note: we ignore the "tsiz" (text size) display option of ps because it's
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// always zero (tested on 10.5 and 10.6).
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool GetProcessMemoryInfoUsingPS(
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<base::ProcessId>& pid_list,
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const char kPsPathName[] = "/bin/ps";
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> argv;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  argv.push_back(kPsPathName);
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Get resident set size, virtual memory size.
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  argv.push_back("-o");
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("pid=,rss=,vsz=");
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only display the specified PIDs.
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin();
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      it != pid_list.end(); ++it) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    argv.push_back("-p");
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    argv.push_back(base::Int64ToString(static_cast<int64>(*it)));
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string output;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CommandLine command_line(argv);
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Limit output read to a megabyte for safety.
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data.";
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::istringstream in(output, std::istringstream::in);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string line;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Process lines until done.
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (true) {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The format is as specified above to ps (see ps(1)):
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    //   "-o pid=,rss=,vsz=".
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Try to read the PID; if we get it, we should be able to get the rest of
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the line.
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    pid_t pid;
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    in >> pid;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (in.eof())
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid];
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.pid = pid;
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    in >> proc_info.rss;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    in >> proc_info.vsize;
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rss *= 1024;                // Convert from kilobytes to bytes.
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.vsize *= 1024;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    in.ignore(1, ' ');                    // Eat the space.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::getline(in, proc_info.command);  // Get the rest of the line.
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!in.good()) {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "Error parsing output from " << kPsPathName << ".";
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!proc_info.pid || ! proc_info.vsize) {
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(WARNING) << "Invalid data from " << kPsPathName << ".";
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Record the process information.
18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info_entries[proc_info.pid] = proc_info;
18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool GetProcessMemoryInfoUsingTop(
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const char kTopPathName[] = "/usr/bin/top";
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::vector<std::string> argv;
19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back(kTopPathName);
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // -stats tells top to print just the given fields as ordered.
19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("-stats");
19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("pid,"    // Process ID
20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "rsize,"  // Resident memory
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "rshrd,"  // Resident shared memory
20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "rprvt,"  // Resident private memory
20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "vsize"); // Total virtual memory
20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Run top in logging (non-interactive) mode.
20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("-l");
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("1");
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Set the delay between updates to 0.
20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("-s");
20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("0");
21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string output;
21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CommandLine command_line(argv);
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Limit output read to a megabyte for safety.
21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data.";
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Process lines until done. Lines should look something like this:
22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // PID    RSIZE  RSHRD  RPRVT  VSIZE
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // 58539  1276K+ 336K+  740K+  2378M+
22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // 58485  1888K+ 592K+  1332K+ 2383M+
22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::istringstream top_in(output, std::istringstream::in);
22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string line;
22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (std::getline(top_in, line)) {
22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::istringstream in(line, std::istringstream::in);
22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Try to read the PID.
22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    pid_t pid;
23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    in >> pid;
23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (in.fail())
23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Make sure that caller is interested in this process.
23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (proc_info_entries.find(pid) == proc_info_entries.end())
23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Skip the - or + sign that top puts after the pid.
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    in.get();
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    uint64_t values[4];
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    size_t i;
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    for (i = 0; i < arraysize(values); i++) {
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      in >> values[i];
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (in.fail())
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        break;
24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::string unit;
24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      in >> unit;
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (in.fail())
25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        break;
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (unit.empty())
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        break;
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      uint64_t scale;
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!ConvertByteUnitToScale(unit[0], &scale))
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        break;
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      values[i] *= scale;
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (i != arraysize(values))
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid];
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rss = values[0];
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rshrd = values[1];
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rprvt = values[2];
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.vsize = values[3];
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Record the process information.
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info_entries[proc_info.pid] = proc_info;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool GetProcessMemoryInfoUsingTop_10_5(
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const char kTopPathName[] = "/usr/bin/top";
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::vector<std::string> argv;
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back(kTopPathName);
28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // -p tells top to print just the given fields as ordered.
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("-p");
28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("^aaaaaaaaaaaaaaaaaaaa "  // Process ID (PID)
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "^jjjjjjjjjjjjjjjjjjjj "  // Resident memory (RSIZE)
28572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "^iiiiiiiiiiiiiiiiiiii "  // Resident shared memory (RSHRD)
28672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "^hhhhhhhhhhhhhhhhhhhh "  // Resident private memory (RPRVT)
28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 "^llllllllllllllllllll"); // Total virtual memory (VSIZE)
28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Run top in logging (non-interactive) mode.
28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("-l");
29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("1");
29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Set the delay between updates to 0.
29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("-s");
29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  argv.push_back("0");
29472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string output;
29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CommandLine command_line(argv);
29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Limit output read to a megabyte for safety.
29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data.";
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Process lines until done. Lines should look something like this:
30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // PID      RSIZE     RSHRD     RPRVT     VSIZE
30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // 16943    815104    262144    290816    18489344
30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // 16922    954368    720896    278528    18976768
30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::istringstream top_in(output, std::istringstream::in);
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string line;
30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (std::getline(top_in, line)) {
31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::istringstream in(line, std::istringstream::in);
31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Try to read the PID.
31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    pid_t pid;
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    in >> pid;
31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (in.fail())
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Make sure that caller is interested in this process.
31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (proc_info_entries.find(pid) == proc_info_entries.end())
32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    uint64_t values[4];
32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    size_t i;
32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    for (i = 0; i < arraysize(values); i++) {
32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      in >> values[i];
32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (in.fail())
32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        break;
32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (i != arraysize(values))
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid];
33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rss = values[0];
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rshrd = values[1];
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.rprvt = values[2];
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.vsize = values[3];
33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Record the process information.
33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info_entries[proc_info.pid] = proc_info;
33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) {
34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Reset();
34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Nothing to do if no PIDs given.
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (pid_list.empty())
35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (pid_list.size() > kMaxPidListSize) {
35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // The spec says |pid_list| *must* not have more than this many entries.
35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED();
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Get basic process info from KERN_PROC.
35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (std::vector<base::ProcessId>::iterator it = pid_list.begin();
35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       it != pid_list.end(); ++it) {
36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ProcInfoEntry proc_info;
36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.pid = *it;
36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    kinfo_proc kinfo;
36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!GetKInfoForProcessID(*it, &kinfo))
36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.ppid = kinfo.kp_eproc.e_ppid;
36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.uid = kinfo.kp_eproc.e_pcred.p_ruid;
36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.euid = kinfo.kp_eproc.e_ucred.cr_uid;
37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Note, p_comm is truncated to 16 characters.
37172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info.command = kinfo.kp_proc.p_comm;
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proc_info_entries_[*it] = proc_info;
37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Use KERN_PROCARGS to get the full executable name. This may fail if this
37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // process doesn't have privileges to inspect the target process.
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (std::vector<base::ProcessId>::iterator it = pid_list.begin();
37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       it != pid_list.end(); ++it) {
37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string exectuable_name;
38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (GetExecutableNameForProcessID(*it, &exectuable_name)) {
38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ProcInfoEntry proc_info = proc_info_entries_[*it];
38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      proc_info.command = exectuable_name;
38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Get memory information using top.
38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool memory_info_success = false;
38872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int32 major, minor, bugfix;
38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (major == 10 && minor == 5)
39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    memory_info_success = GetProcessMemoryInfoUsingTop_10_5(proc_info_entries_);
39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  else if ((major == 10 && minor >= 6) || major > 10)
39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    memory_info_success = GetProcessMemoryInfoUsingTop(proc_info_entries_);
39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If top didn't work then fall back to ps.
39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!memory_info_success) {
39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    memory_info_success = GetProcessMemoryInfoUsingPS(pid_list,
39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                      proc_info_entries_);
39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return memory_info_success;
40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Clear all the stored information.
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProcessInfoSnapshot::Reset() {
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  proc_info_entries_.clear();
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProcessInfoSnapshot::GetProcInfo(int pid,
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      ProcInfoEntry* proc_info) const {
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::map<int,ProcInfoEntry>::const_iterator it = proc_info_entries_.find(pid);
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == proc_info_entries_.end())
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *proc_info = it->second;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProcessInfoSnapshot::GetCommittedKBytesOfPID(
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int pid,
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::CommittedKBytes* usage) const {
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Try to avoid crashing on a bug; stats aren't usually so crucial.
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!usage) {
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Failure of |GetProcInfo()| is "normal", due to racing.
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ProcInfoEntry proc_info;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetProcInfo(pid, &proc_info)) {
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    usage->priv = 0;
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    usage->mapped = 0;
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    usage->image = 0;
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  usage->priv = proc_info.vsize / 1024;
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  usage->mapped = 0;
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  usage->image = 0;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProcessInfoSnapshot::GetWorkingSetKBytesOfPID(
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int pid,
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::WorkingSetKBytes* ws_usage) const {
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Try to avoid crashing on a bug; stats aren't usually so crucial.
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ws_usage) {
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Failure of |GetProcInfo()| is "normal", due to racing.
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ProcInfoEntry proc_info;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetProcInfo(pid, &proc_info)) {
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ws_usage->priv = 0;
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ws_usage->shareable = 0;
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ws_usage->shared = 0;
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ws_usage->priv = proc_info.rprvt / 1024;
46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ws_usage->shareable = proc_info.rss / 1024;
46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ws_usage->shared = proc_info.rshrd / 1024;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
466