[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/process_info_snapshot.h" |
| 6 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 7 | #include <sys/sysctl.h> |
| 8 | |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 9 | #include <sstream> |
| 10 | |
[email protected] | 5d91c9e | 2010-07-28 17:25:28 | [diff] [blame] | 11 | #include "base/command_line.h" |
[email protected] | 983ef7f | 2010-01-04 16:17:13 | [diff] [blame] | 12 | #include "base/logging.h" |
[email protected] | ba64e2b | 2011-06-14 18:18:38 | [diff] [blame] | 13 | #include "base/mac/mac_util.h" |
[email protected] | 528c56d | 2010-07-30 19:28:44 | [diff] [blame] | 14 | #include "base/string_number_conversions.h" |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 15 | #include "base/string_util.h" |
[email protected] | 34b9963 | 2011-01-01 01:01:06 | [diff] [blame] | 16 | #include "base/threading/thread.h" |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 17 | |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 18 | // Default constructor. |
| 19 | ProcessInfoSnapshot::ProcessInfoSnapshot() { } |
| 20 | |
| 21 | // Destructor: just call |Reset()| to release everything. |
| 22 | ProcessInfoSnapshot::~ProcessInfoSnapshot() { |
| 23 | Reset(); |
| 24 | } |
| 25 | |
[email protected] | 983ef7f | 2010-01-04 16:17:13 | [diff] [blame] | 26 | const size_t ProcessInfoSnapshot::kMaxPidListSize = 1000; |
| 27 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 28 | static bool GetKInfoForProcessID(pid_t pid, kinfo_proc* kinfo) { |
| 29 | int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; |
| 30 | size_t len = sizeof(*kinfo); |
| 31 | if (sysctl(mib, arraysize(mib), kinfo, &len, NULL, 0) != 0) { |
| 32 | PLOG(ERROR) << "sysctl() for KERN_PROC"; |
| 33 | return false; |
| 34 | } |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 35 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 36 | if (len == 0) { |
| 37 | // If the process isn't found then sysctl returns a length of 0. |
| 38 | return false; |
| 39 | } |
| 40 | |
| 41 | return true; |
| 42 | } |
| 43 | |
| 44 | static bool GetExecutableNameForProcessID( |
| 45 | pid_t pid, |
| 46 | std::string* executable_name) { |
| 47 | if (!executable_name) { |
[email protected] | 983ef7f | 2010-01-04 16:17:13 | [diff] [blame] | 48 | NOTREACHED(); |
| 49 | return false; |
| 50 | } |
| 51 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 52 | static int s_arg_max = 0; |
| 53 | if (s_arg_max == 0) { |
| 54 | int mib[] = {CTL_KERN, KERN_ARGMAX}; |
| 55 | size_t size = sizeof(s_arg_max); |
| 56 | if (sysctl(mib, arraysize(mib), &s_arg_max, &size, NULL, 0) != 0) |
| 57 | PLOG(ERROR) << "sysctl() for KERN_ARGMAX"; |
| 58 | } |
| 59 | |
| 60 | if (s_arg_max == 0) |
| 61 | return false; |
| 62 | |
| 63 | int mib[] = {CTL_KERN, KERN_PROCARGS, pid}; |
| 64 | size_t size = s_arg_max; |
| 65 | executable_name->resize(s_arg_max + 1); |
| 66 | if (sysctl(mib, arraysize(mib), &(*executable_name)[0], |
| 67 | &size, NULL, 0) != 0) { |
| 68 | // Don't log the error since it's normal for this to fail. |
| 69 | return false; |
| 70 | } |
| 71 | |
| 72 | // KERN_PROCARGS returns multiple NULL terminated strings. Truncate |
| 73 | // executable_name to just the first string. |
| 74 | size_t end_pos = executable_name->find('\0'); |
| 75 | if (end_pos == std::string::npos) { |
| 76 | return false; |
| 77 | } |
| 78 | |
| 79 | executable_name->resize(end_pos); |
| 80 | return true; |
| 81 | } |
| 82 | |
| 83 | // Converts a byte unit such as 'K' or 'M' into the scale for the unit. |
| 84 | // The scale can then be used to calculate the number of bytes in a value. |
| 85 | // The units are based on humanize_number(). See: |
| 86 | // http://www.opensource.apple.com/source/libutil/libutil-21/humanize_number.c |
| 87 | static bool ConvertByteUnitToScale(char unit, uint64_t* out_scale) { |
| 88 | int shift = 0; |
| 89 | switch (unit) { |
| 90 | case 'B': |
| 91 | shift = 0; |
| 92 | break; |
| 93 | case 'K': |
| 94 | case 'k': |
| 95 | shift = 1; |
| 96 | break; |
| 97 | case 'M': |
| 98 | shift = 2; |
| 99 | break; |
| 100 | case 'G': |
| 101 | shift = 3; |
| 102 | break; |
| 103 | case 'T': |
| 104 | shift = 4; |
| 105 | break; |
| 106 | case 'P': |
| 107 | shift = 5; |
| 108 | break; |
| 109 | case 'E': |
| 110 | shift = 6; |
| 111 | break; |
| 112 | default: |
| 113 | return false; |
| 114 | } |
| 115 | |
| 116 | uint64_t scale = 1; |
| 117 | for (int i = 0; i < shift; i++) |
| 118 | scale *= 1024; |
| 119 | *out_scale = scale; |
| 120 | |
| 121 | return true; |
| 122 | } |
| 123 | |
| 124 | // Capture the information by calling '/bin/ps'. |
| 125 | // Note: we ignore the "tsiz" (text size) display option of ps because it's |
| 126 | // always zero (tested on 10.5 and 10.6). |
| 127 | static bool GetProcessMemoryInfoUsingPS( |
| 128 | const std::vector<base::ProcessId>& pid_list, |
| 129 | std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 130 | const FilePath kProgram("/bin/ps"); |
| 131 | CommandLine command_line(kProgram); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 132 | |
| 133 | // Get resident set size, virtual memory size. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 134 | command_line.AppendArg("-o"); |
| 135 | command_line.AppendArg("pid=,rss=,vsz="); |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 136 | // Only display the specified PIDs. |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 137 | for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin(); |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 138 | it != pid_list.end(); ++it) { |
| 139 | command_line.AppendArg("-p"); |
| 140 | command_line.AppendArg(base::Int64ToString(static_cast<int64>(*it))); |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | std::string output; |
[email protected] | 983ef7f | 2010-01-04 16:17:13 | [diff] [blame] | 144 | // Limit output read to a megabyte for safety. |
| 145 | if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 146 | LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 147 | return false; |
| 148 | } |
| 149 | |
| 150 | std::istringstream in(output, std::istringstream::in); |
| 151 | std::string line; |
| 152 | |
| 153 | // Process lines until done. |
| 154 | while (true) { |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 155 | // The format is as specified above to ps (see ps(1)): |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 156 | // "-o pid=,rss=,vsz=". |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 157 | // Try to read the PID; if we get it, we should be able to get the rest of |
| 158 | // the line. |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 159 | pid_t pid; |
| 160 | in >> pid; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 161 | if (in.eof()) |
| 162 | break; |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 163 | |
| 164 | ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; |
| 165 | proc_info.pid = pid; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 166 | in >> proc_info.rss; |
| 167 | in >> proc_info.vsize; |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 168 | proc_info.rss *= 1024; // Convert from kilobytes to bytes. |
| 169 | proc_info.vsize *= 1024; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 170 | in.ignore(1, ' '); // Eat the space. |
| 171 | std::getline(in, proc_info.command); // Get the rest of the line. |
| 172 | if (!in.good()) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 173 | LOG(ERROR) << "Error parsing output from " << kProgram.value() << "."; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 174 | return false; |
| 175 | } |
| 176 | |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 177 | if (!proc_info.pid || ! proc_info.vsize) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 178 | LOG(WARNING) << "Invalid data from " << kProgram.value() << "."; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 179 | return false; |
| 180 | } |
| 181 | |
| 182 | // Record the process information. |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 183 | proc_info_entries[proc_info.pid] = proc_info; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | return true; |
| 187 | } |
| 188 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 189 | static bool GetProcessMemoryInfoUsingTop( |
| 190 | std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 191 | const FilePath kProgram("/usr/bin/top"); |
| 192 | CommandLine command_line(kProgram); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 193 | |
| 194 | // -stats tells top to print just the given fields as ordered. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 195 | command_line.AppendArg("-stats"); |
| 196 | command_line.AppendArg("pid," // Process ID |
| 197 | "rsize," // Resident memory |
| 198 | "rshrd," // Resident shared memory |
| 199 | "rprvt," // Resident private memory |
| 200 | "vsize"); // Total virtual memory |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 201 | // Run top in logging (non-interactive) mode. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 202 | command_line.AppendArg("-l"); |
| 203 | command_line.AppendArg("1"); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 204 | // Set the delay between updates to 0. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 205 | command_line.AppendArg("-s"); |
| 206 | command_line.AppendArg("0"); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 207 | |
| 208 | std::string output; |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 209 | // Limit output read to a megabyte for safety. |
| 210 | if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 211 | LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 212 | return false; |
| 213 | } |
| 214 | |
| 215 | // Process lines until done. Lines should look something like this: |
| 216 | // PID RSIZE RSHRD RPRVT VSIZE |
| 217 | // 58539 1276K+ 336K+ 740K+ 2378M+ |
| 218 | // 58485 1888K+ 592K+ 1332K+ 2383M+ |
| 219 | std::istringstream top_in(output, std::istringstream::in); |
| 220 | std::string line; |
| 221 | while (std::getline(top_in, line)) { |
| 222 | std::istringstream in(line, std::istringstream::in); |
| 223 | |
| 224 | // Try to read the PID. |
| 225 | pid_t pid; |
| 226 | in >> pid; |
| 227 | if (in.fail()) |
| 228 | continue; |
| 229 | |
| 230 | // Make sure that caller is interested in this process. |
| 231 | if (proc_info_entries.find(pid) == proc_info_entries.end()) |
| 232 | continue; |
| 233 | |
| 234 | // Skip the - or + sign that top puts after the pid. |
| 235 | in.get(); |
| 236 | |
| 237 | uint64_t values[4]; |
| 238 | size_t i; |
| 239 | for (i = 0; i < arraysize(values); i++) { |
| 240 | in >> values[i]; |
| 241 | if (in.fail()) |
| 242 | break; |
| 243 | std::string unit; |
| 244 | in >> unit; |
| 245 | if (in.fail()) |
| 246 | break; |
| 247 | |
[email protected] | f6b8ce3 | 2011-03-02 00:03:18 | [diff] [blame] | 248 | if (unit.empty()) |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 249 | break; |
| 250 | |
| 251 | uint64_t scale; |
| 252 | if (!ConvertByteUnitToScale(unit[0], &scale)) |
| 253 | break; |
| 254 | values[i] *= scale; |
| 255 | } |
| 256 | if (i != arraysize(values)) |
| 257 | continue; |
| 258 | |
| 259 | ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; |
| 260 | proc_info.rss = values[0]; |
| 261 | proc_info.rshrd = values[1]; |
| 262 | proc_info.rprvt = values[2]; |
| 263 | proc_info.vsize = values[3]; |
| 264 | // Record the process information. |
| 265 | proc_info_entries[proc_info.pid] = proc_info; |
| 266 | } |
| 267 | |
| 268 | return true; |
| 269 | } |
| 270 | |
| 271 | static bool GetProcessMemoryInfoUsingTop_10_5( |
| 272 | std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 273 | const FilePath kProgram("/usr/bin/top"); |
| 274 | CommandLine command_line(kProgram); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 275 | |
| 276 | // -p tells top to print just the given fields as ordered. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 277 | command_line.AppendArg("-p"); |
| 278 | command_line.AppendArg( |
| 279 | "^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID) |
| 280 | "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE) |
| 281 | "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD) |
| 282 | "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT) |
| 283 | "^llllllllllllllllllll"); // Total virtual memory (VSIZE) |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 284 | // Run top in logging (non-interactive) mode. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 285 | command_line.AppendArg("-l"); |
| 286 | command_line.AppendArg("1"); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 287 | // Set the delay between updates to 0. |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 288 | command_line.AppendArg("-s"); |
| 289 | command_line.AppendArg("0"); |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 290 | |
| 291 | std::string output; |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 292 | // Limit output read to a megabyte for safety. |
| 293 | if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
[email protected] | a40ca430 | 2011-05-14 01:10:24 | [diff] [blame] | 294 | LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 295 | return false; |
| 296 | } |
| 297 | |
| 298 | // Process lines until done. Lines should look something like this: |
| 299 | // PID RSIZE RSHRD RPRVT VSIZE |
| 300 | // 16943 815104 262144 290816 18489344 |
| 301 | // 16922 954368 720896 278528 18976768 |
| 302 | std::istringstream top_in(output, std::istringstream::in); |
| 303 | std::string line; |
| 304 | while (std::getline(top_in, line)) { |
| 305 | std::istringstream in(line, std::istringstream::in); |
| 306 | |
| 307 | // Try to read the PID. |
| 308 | pid_t pid; |
| 309 | in >> pid; |
| 310 | if (in.fail()) |
| 311 | continue; |
| 312 | |
| 313 | // Make sure that caller is interested in this process. |
| 314 | if (proc_info_entries.find(pid) == proc_info_entries.end()) |
| 315 | continue; |
| 316 | |
| 317 | uint64_t values[4]; |
| 318 | size_t i; |
| 319 | for (i = 0; i < arraysize(values); i++) { |
| 320 | in >> values[i]; |
| 321 | if (in.fail()) |
| 322 | break; |
| 323 | } |
| 324 | if (i != arraysize(values)) |
| 325 | continue; |
| 326 | |
| 327 | ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; |
| 328 | proc_info.rss = values[0]; |
| 329 | proc_info.rshrd = values[1]; |
| 330 | proc_info.rprvt = values[2]; |
| 331 | proc_info.vsize = values[3]; |
| 332 | // Record the process information. |
| 333 | proc_info_entries[proc_info.pid] = proc_info; |
| 334 | } |
| 335 | |
| 336 | return true; |
| 337 | } |
| 338 | |
| 339 | |
| 340 | bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) { |
| 341 | Reset(); |
| 342 | |
| 343 | // Nothing to do if no PIDs given. |
[email protected] | f6b8ce3 | 2011-03-02 00:03:18 | [diff] [blame] | 344 | if (pid_list.empty()) |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 345 | return true; |
| 346 | if (pid_list.size() > kMaxPidListSize) { |
| 347 | // The spec says |pid_list| *must* not have more than this many entries. |
| 348 | NOTREACHED(); |
| 349 | return false; |
| 350 | } |
| 351 | |
| 352 | // Get basic process info from KERN_PROC. |
| 353 | for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); |
| 354 | it != pid_list.end(); ++it) { |
| 355 | ProcInfoEntry proc_info; |
| 356 | proc_info.pid = *it; |
| 357 | |
| 358 | kinfo_proc kinfo; |
| 359 | if (!GetKInfoForProcessID(*it, &kinfo)) |
| 360 | return false; |
| 361 | |
| 362 | proc_info.ppid = kinfo.kp_eproc.e_ppid; |
| 363 | proc_info.uid = kinfo.kp_eproc.e_pcred.p_ruid; |
| 364 | proc_info.euid = kinfo.kp_eproc.e_ucred.cr_uid; |
| 365 | // Note, p_comm is truncated to 16 characters. |
| 366 | proc_info.command = kinfo.kp_proc.p_comm; |
| 367 | proc_info_entries_[*it] = proc_info; |
| 368 | } |
| 369 | |
| 370 | // Use KERN_PROCARGS to get the full executable name. This may fail if this |
| 371 | // process doesn't have privileges to inspect the target process. |
| 372 | for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); |
| 373 | it != pid_list.end(); ++it) { |
| 374 | std::string exectuable_name; |
| 375 | if (GetExecutableNameForProcessID(*it, &exectuable_name)) { |
| 376 | ProcInfoEntry proc_info = proc_info_entries_[*it]; |
| 377 | proc_info.command = exectuable_name; |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | // Get memory information using top. |
| 382 | bool memory_info_success = false; |
[email protected] | ba64e2b | 2011-06-14 18:18:38 | [diff] [blame] | 383 | if (base::mac::IsOSLeopardOrEarlier()) |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 384 | memory_info_success = GetProcessMemoryInfoUsingTop_10_5(proc_info_entries_); |
[email protected] | ba64e2b | 2011-06-14 18:18:38 | [diff] [blame] | 385 | else |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 386 | memory_info_success = GetProcessMemoryInfoUsingTop(proc_info_entries_); |
| 387 | |
| 388 | // If top didn't work then fall back to ps. |
| 389 | if (!memory_info_success) { |
| 390 | memory_info_success = GetProcessMemoryInfoUsingPS(pid_list, |
| 391 | proc_info_entries_); |
| 392 | } |
| 393 | |
| 394 | return memory_info_success; |
| 395 | } |
| 396 | |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 397 | // Clear all the stored information. |
| 398 | void ProcessInfoSnapshot::Reset() { |
| 399 | proc_info_entries_.clear(); |
| 400 | } |
| 401 | |
| 402 | bool ProcessInfoSnapshot::GetProcInfo(int pid, |
| 403 | ProcInfoEntry* proc_info) const { |
| 404 | std::map<int,ProcInfoEntry>::const_iterator it = proc_info_entries_.find(pid); |
| 405 | if (it == proc_info_entries_.end()) |
| 406 | return false; |
| 407 | |
| 408 | *proc_info = it->second; |
| 409 | return true; |
| 410 | } |
| 411 | |
| 412 | bool ProcessInfoSnapshot::GetCommittedKBytesOfPID( |
| 413 | int pid, |
| 414 | base::CommittedKBytes* usage) const { |
| 415 | // Try to avoid crashing on a bug; stats aren't usually so crucial. |
| 416 | if (!usage) { |
| 417 | NOTREACHED(); |
| 418 | return false; |
| 419 | } |
| 420 | |
| 421 | // Failure of |GetProcInfo()| is "normal", due to racing. |
| 422 | ProcInfoEntry proc_info; |
| 423 | if (!GetProcInfo(pid, &proc_info)) { |
| 424 | usage->priv = 0; |
| 425 | usage->mapped = 0; |
| 426 | usage->image = 0; |
| 427 | return false; |
| 428 | } |
| 429 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 430 | usage->priv = proc_info.vsize / 1024; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 431 | usage->mapped = 0; |
| 432 | usage->image = 0; |
| 433 | return true; |
| 434 | } |
| 435 | |
| 436 | bool ProcessInfoSnapshot::GetWorkingSetKBytesOfPID( |
| 437 | int pid, |
| 438 | base::WorkingSetKBytes* ws_usage) const { |
| 439 | // Try to avoid crashing on a bug; stats aren't usually so crucial. |
| 440 | if (!ws_usage) { |
| 441 | NOTREACHED(); |
| 442 | return false; |
| 443 | } |
| 444 | |
| 445 | // Failure of |GetProcInfo()| is "normal", due to racing. |
| 446 | ProcInfoEntry proc_info; |
| 447 | if (!GetProcInfo(pid, &proc_info)) { |
| 448 | ws_usage->priv = 0; |
| 449 | ws_usage->shareable = 0; |
| 450 | ws_usage->shared = 0; |
| 451 | return false; |
| 452 | } |
| 453 | |
[email protected] | b23d013 | 2011-01-12 00:20:45 | [diff] [blame] | 454 | ws_usage->priv = proc_info.rprvt / 1024; |
| 455 | ws_usage->shareable = proc_info.rss / 1024; |
| 456 | ws_usage->shared = proc_info.rshrd / 1024; |
[email protected] | f164cea | 2009-11-05 23:37:40 | [diff] [blame] | 457 | return true; |
| 458 | } |