Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/process_info_snapshot.h" | 5 #include "chrome/browser/process_info_snapshot.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 #include <sys/sysctl.h> | |
|
Mark Mentovai
2011/01/04 20:09:31
C system headers should precede C++ system headers
sail
2011/01/06 00:22:59
Done.
| |
| 8 | 9 |
| 9 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
| 12 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/sys_info.h" | |
| 13 #include "base/thread.h" | 15 #include "base/thread.h" |
| 14 | 16 |
| 15 // Implementation for the Mac; calls '/bin/ps' for information when | |
| 16 // |Sample()| is called. | |
| 17 | |
| 18 // Default constructor. | 17 // Default constructor. |
| 19 ProcessInfoSnapshot::ProcessInfoSnapshot() { } | 18 ProcessInfoSnapshot::ProcessInfoSnapshot() { } |
| 20 | 19 |
| 21 // Destructor: just call |Reset()| to release everything. | 20 // Destructor: just call |Reset()| to release everything. |
| 22 ProcessInfoSnapshot::~ProcessInfoSnapshot() { | 21 ProcessInfoSnapshot::~ProcessInfoSnapshot() { |
| 23 Reset(); | 22 Reset(); |
| 24 } | 23 } |
| 25 | 24 |
| 26 const size_t ProcessInfoSnapshot::kMaxPidListSize = 1000; | 25 const size_t ProcessInfoSnapshot::kMaxPidListSize = 1000; |
| 27 | 26 |
| 27 static bool GetKInfoForProcessID(kinfo_proc* kinfo, pid_t pid) { | |
|
Mark Mentovai
2011/01/04 20:09:31
I suggest putting “in” parameters before “out” one
sail
2011/01/06 00:22:59
Done.
| |
| 28 int mib[4]; | |
|
Mark Mentovai
2011/01/04 20:09:31
Why not just use int mib[] = {CTL_KERN, KERN_PROC,
sail
2011/01/06 00:22:59
Done.
| |
| 29 mib[0] = CTL_KERN; | |
| 30 mib[1] = KERN_PROC; | |
| 31 mib[2] = KERN_PROC_PID; | |
| 32 mib[3] = pid; | |
| 33 | |
| 34 size_t miblen = 4; | |
|
Mark Mentovai
2011/01/04 20:09:31
Why not just use arraysize(mib)? (You don’t even n
sail
2011/01/06 00:22:59
Done.
| |
| 35 size_t len = sizeof(*kinfo); | |
| 36 if (sysctl(mib, miblen, kinfo, &len, NULL, 0) != 0) { | |
| 37 PLOG(ERROR) << "sysctl() for KERN_PROC"; | |
| 38 return false; | |
| 39 } | |
| 40 return true; | |
| 41 } | |
| 42 | |
| 43 static bool GetExecutableNameForProcessID(char** executable_name, pid_t pid) { | |
|
Mark Mentovai
2011/01/04 20:09:31
The interface would probably be better if the out
sail
2011/01/06 00:22:59
Done.
| |
| 44 static bool s_should_init_arg_max = true; | |
|
Mark Mentovai
2011/01/04 20:09:31
These usually work a little better in terms of cod
sail
2011/01/06 00:22:59
Done.
| |
| 45 static int s_arg_max = 0; | |
|
Mark Mentovai
2011/01/04 20:09:31
You may not need two separate variables here, eith
sail
2011/01/06 00:22:59
Done.
| |
| 46 | |
| 47 if (!executable_name) { | |
| 48 NOTREACHED(); | |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 if (s_should_init_arg_max) { | |
|
Mark Mentovai
2011/01/04 20:09:31
The declarations should be closer to the point of
sail
2011/01/06 00:22:59
Done.
| |
| 53 s_should_init_arg_max = false; | |
| 54 int mib[2]; | |
|
Mark Mentovai
2011/01/04 20:09:31
Simplify mib and size as discussed above. Same on
sail
2011/01/06 00:22:59
Done.
| |
| 55 mib[0] = CTL_KERN; | |
| 56 mib[1] = KERN_ARGMAX; | |
| 57 size_t size = sizeof(s_arg_max); | |
| 58 if (sysctl(mib, 2, &s_arg_max, &size, NULL, 0) != 0) { | |
| 59 PLOG(ERROR) << "sysctl() for KERN_ARGMAX"; | |
| 60 } | |
| 61 } | |
| 62 | |
| 63 if (s_arg_max == 0) { | |
| 64 return false; | |
| 65 } | |
| 66 | |
| 67 int mib[3]; | |
| 68 mib[0] = CTL_KERN; | |
| 69 mib[1] = KERN_PROCARGS; | |
| 70 mib[2] = pid; | |
| 71 char *arg = new char[s_arg_max]; | |
| 72 size_t size = s_arg_max; | |
| 73 if (sysctl(mib, 3, arg, &size, NULL, 0) != 0) { | |
| 74 // Don't log the error since it's normal for this to fail. | |
| 75 return false; | |
|
Mark Mentovai
2011/01/04 20:09:31
Leaks arg? See, the ownership model is spaghetti h
sail
2011/01/06 00:22:59
Done.
| |
| 76 } | |
| 77 | |
| 78 *executable_name = arg; | |
| 79 return true; | |
| 80 } | |
| 81 | |
| 82 // The units are based on humanize_number(). See: | |
| 83 // http://www.opensource.apple.com/source/libutil/libutil-21/humanize_number.c | |
|
Mark Mentovai
2011/01/04 20:09:31
The function name doesn’t really tell me what to p
sail
2011/01/06 00:22:59
Done.
| |
| 84 static bool ConvertUnitToScale(std::string unit, uint64_t* scale) { | |
|
Mark Mentovai
2011/01/04 20:09:31
unit can be a const std::string&.
unit can also j
sail
2011/01/06 00:22:59
Done.
| |
| 85 if (unit.size() == 0) { | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 uint64_t shift = 0; | |
|
Mark Mentovai
2011/01/04 20:09:31
This is fine as just an int.
sail
2011/01/06 00:23:00
Done.
| |
| 90 switch (unit[0]) { | |
| 91 case 'B': | |
| 92 shift = 0; | |
| 93 break; | |
| 94 case 'K': | |
|
Mark Mentovai
2011/01/04 20:09:31
Care about lowercase 'k'?
sail
2011/01/06 00:23:00
Done. Libtop doesn't use lowercase 'k' but it does
| |
| 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 *scale = 1; | |
| 117 for (size_t i = 0; i < shift; i++) { | |
|
Mark Mentovai
2011/01/04 20:09:31
This is fine as just an int too.
sail
2011/01/06 00:23:00
Done.
| |
| 118 *scale *= 1024; | |
|
Mark Mentovai
2011/01/04 20:09:31
Rather than dereferencing scale each time through
sail
2011/01/06 00:23:00
Done.
| |
| 119 } | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 28 // Capture the information by calling '/bin/ps'. | 123 // Capture the information by calling '/bin/ps'. |
| 29 // Note: we ignore the "tsiz" (text size) display option of ps because it's | 124 // Note: we ignore the "tsiz" (text size) display option of ps because it's |
| 30 // always zero (tested on 10.5 and 10.6). | 125 // always zero (tested on 10.5 and 10.6). |
| 31 bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) { | 126 static bool GetProcessMemoryInfoUsingPS( |
| 127 const std::vector<base::ProcessId>& pid_list, | |
| 128 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | |
| 32 const char* kPsPathName = "/bin/ps"; | 129 const char* kPsPathName = "/bin/ps"; |
|
Mark Mentovai
2011/01/04 20:09:31
Some of the comments below, like using a const cha
sail
2011/01/06 00:23:00
Done.
| |
| 33 Reset(); | |
| 34 | |
| 35 // Nothing to do if no PIDs given. | |
| 36 if (pid_list.size() == 0) | |
| 37 return true; | |
| 38 if (pid_list.size() > kMaxPidListSize) { | |
| 39 // The spec says |pid_list| *must* not have more than this many entries. | |
| 40 NOTREACHED(); | |
| 41 return false; | |
| 42 } | |
| 43 | |
| 44 std::vector<std::string> argv; | 130 std::vector<std::string> argv; |
| 45 argv.push_back(kPsPathName); | 131 argv.push_back(kPsPathName); |
| 46 // Get PID, PPID, (real) UID, effective UID, resident set size, virtual memory | 132 |
| 47 // size, and command. | 133 // Get resident set size, virtual memory size. |
| 48 argv.push_back("-o"); | 134 argv.push_back("-o"); |
| 49 argv.push_back("pid=,ppid=,ruid=,uid=,rss=,vsz=,comm="); | 135 argv.push_back("pid=,rss=,vsz="); |
| 50 // Only display the specified PIDs. | 136 // Only display the specified PIDs. |
| 51 for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); | 137 for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin(); |
| 52 it != pid_list.end(); ++it) { | 138 it != pid_list.end(); ++it) { |
| 53 argv.push_back("-p"); | 139 argv.push_back("-p"); |
| 54 argv.push_back(base::Int64ToString(static_cast<int64>(*it))); | 140 argv.push_back(base::Int64ToString(static_cast<int64>(*it))); |
| 55 } | 141 } |
| 56 | 142 |
| 57 std::string output; | 143 std::string output; |
| 58 CommandLine command_line(argv); | 144 CommandLine command_line(argv); |
| 59 // Limit output read to a megabyte for safety. | 145 // Limit output read to a megabyte for safety. |
| 60 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | 146 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { |
| 61 LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data."; | 147 LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data."; |
| 62 return false; | 148 return false; |
| 63 } | 149 } |
| 64 | 150 |
| 65 std::istringstream in(output, std::istringstream::in); | 151 std::istringstream in(output, std::istringstream::in); |
| 66 std::string line; | 152 std::string line; |
| 67 | 153 |
| 68 // Process lines until done. | 154 // Process lines until done. |
| 69 while (true) { | 155 while (true) { |
| 70 ProcInfoEntry proc_info; | |
| 71 | |
| 72 // The format is as specified above to ps (see ps(1)): | 156 // The format is as specified above to ps (see ps(1)): |
| 73 // "-o pid=,ppid=,ruid=,uid=,rss=,vsz=,comm=". | 157 // "-o pid=,rss=,vsz=". |
| 74 // Try to read the PID; if we get it, we should be able to get the rest of | 158 // Try to read the PID; if we get it, we should be able to get the rest of |
| 75 // the line. | 159 // the line. |
| 76 in >> proc_info.pid; | 160 pid_t pid; |
| 161 in >> pid; | |
| 77 if (in.eof()) | 162 if (in.eof()) |
| 78 break; | 163 break; |
| 79 in >> proc_info.ppid; | 164 |
| 80 in >> proc_info.uid; | 165 ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; |
| 81 in >> proc_info.euid; | 166 proc_info.pid = pid; |
| 82 in >> proc_info.rss; | 167 in >> proc_info.rss; |
| 83 in >> proc_info.vsize; | 168 in >> proc_info.vsize; |
| 169 proc_info.rss *= 1024; // Convert from kilobytes to bytes. | |
| 170 proc_info.vsize *= 1024; | |
| 84 in.ignore(1, ' '); // Eat the space. | 171 in.ignore(1, ' '); // Eat the space. |
| 85 std::getline(in, proc_info.command); // Get the rest of the line. | 172 std::getline(in, proc_info.command); // Get the rest of the line. |
| 86 if (!in.good()) { | 173 if (!in.good()) { |
| 87 LOG(ERROR) << "Error parsing output from " << kPsPathName << "."; | 174 LOG(ERROR) << "Error parsing output from " << kPsPathName << "."; |
| 88 return false; | 175 return false; |
| 89 } | 176 } |
| 90 | 177 |
| 91 // Make sure the new PID isn't already in our list. | |
| 92 if (proc_info_entries_.find(proc_info.pid) != proc_info_entries_.end()) { | |
| 93 LOG(ERROR) << "Duplicate PID in output from " << kPsPathName << "."; | |
| 94 return false; | |
| 95 } | |
| 96 | |
| 97 if (!proc_info.pid || ! proc_info.vsize) { | 178 if (!proc_info.pid || ! proc_info.vsize) { |
| 98 LOG(WARNING) << "Invalid data from " << kPsPathName << "."; | 179 LOG(WARNING) << "Invalid data from " << kPsPathName << "."; |
| 99 return false; | 180 return false; |
| 100 } | 181 } |
| 101 | 182 |
| 102 // Record the process information. | 183 // Record the process information. |
| 103 proc_info_entries_[proc_info.pid] = proc_info; | 184 proc_info_entries[proc_info.pid] = proc_info; |
| 104 } | 185 } |
| 105 | 186 |
| 106 return true; | 187 return true; |
| 107 } | 188 } |
| 108 | 189 |
| 190 static bool GetProcessMemoryInfoUsingTop( | |
| 191 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | |
| 192 const char* kPsPathName = "/usr/bin/top"; | |
|
Mark Mentovai
2011/01/04 20:09:31
Isn’t this more like kTopPathName?
And wouldn’t y
sail
2011/01/06 00:23:00
Done.
| |
| 193 std::vector<std::string> argv; | |
| 194 argv.push_back(kPsPathName); | |
| 195 | |
| 196 // -stats tells top to print just the given fields as ordered. | |
| 197 argv.push_back("-stats"); | |
| 198 argv.push_back("pid," // Process ID | |
| 199 "rsize," // Resident memory | |
| 200 "rshrd," // Resident shared memory | |
| 201 "rprvt," // Resident private memory | |
| 202 "vsize"); // Total virtual memory | |
| 203 // Run top in logging (non-interactive) mode. | |
| 204 argv.push_back("-l"); | |
| 205 argv.push_back("1"); | |
| 206 | |
| 207 std::string output; | |
| 208 CommandLine command_line(argv); | |
| 209 // Limit output read to a megabyte for safety. | |
| 210 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | |
| 211 LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data."; | |
| 212 return false; | |
| 213 } | |
| 214 | |
| 215 // Process lines until done. | |
| 216 std::istringstream topIn(output, std::istringstream::in); | |
|
Mark Mentovai
2011/01/04 20:09:31
top_in, not topIn.
sail
2011/01/06 00:23:00
Done.
| |
| 217 std::string line; | |
| 218 while (std::getline(topIn, line)) { | |
|
Mark Mentovai
2011/01/04 20:09:31
Show an example line or two, so that the reader ha
sail
2011/01/06 00:23:00
Done.
| |
| 219 std::istringstream in(line, std::istringstream::in); | |
| 220 | |
| 221 // Try to read the PID. | |
| 222 pid_t pid; | |
| 223 in >> pid; | |
| 224 if (in.fail()) | |
| 225 continue; | |
| 226 | |
| 227 // Make sure that caller is interested in this process. | |
| 228 if (proc_info_entries.find(pid) == proc_info_entries.end()) | |
| 229 continue; | |
| 230 | |
| 231 // Skip the - or + sign that top puts after the pid. | |
| 232 in.get(); | |
| 233 | |
| 234 uint64_t values[4]; | |
| 235 size_t i; | |
| 236 for (i = 0; i < arraysize(values); i++) { | |
| 237 in >> values[i]; | |
| 238 if (in.fail()) | |
| 239 break; | |
| 240 std::string unit; | |
| 241 in >> unit; | |
| 242 if (in.fail()) | |
| 243 break; | |
| 244 | |
| 245 uint64_t scale; | |
| 246 if (!ConvertUnitToScale(unit, &scale)) { | |
| 247 break; | |
| 248 } | |
| 249 values[i] *= scale; | |
| 250 } | |
| 251 if (i != arraysize(values)) | |
| 252 continue; | |
| 253 | |
| 254 ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; | |
| 255 proc_info.rss = values[0]; | |
| 256 proc_info.rshrd = values[1]; | |
| 257 proc_info.rprvt = values[2]; | |
| 258 proc_info.vsize = values[3]; | |
| 259 // Record the process information. | |
| 260 proc_info_entries[proc_info.pid] = proc_info; | |
| 261 } | |
| 262 | |
| 263 return true; | |
| 264 } | |
| 265 | |
| 266 static bool GetProcessMemoryInfoUsingTop_10_5( | |
| 267 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | |
| 268 const char* kPsPathName = "/usr/bin/top"; | |
|
Mark Mentovai
2011/01/04 20:09:31
Refer to similar comments above.
sail
2011/01/06 00:23:00
Done.
| |
| 269 std::vector<std::string> argv; | |
| 270 argv.push_back(kPsPathName); | |
| 271 | |
| 272 // -p tells top to print just the given fields as ordered. | |
| 273 argv.push_back("-p"); | |
| 274 argv.push_back("^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID) | |
| 275 "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE) | |
| 276 "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD) | |
| 277 "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT) | |
| 278 "^llllllllllllllllllll"); // Total virtual memory (VSIZE) | |
| 279 // Run top in logging (non-interactive) mode. | |
| 280 argv.push_back("-l"); | |
| 281 argv.push_back("1"); | |
| 282 | |
| 283 std::string output; | |
| 284 CommandLine command_line(argv); | |
| 285 // Limit output read to a megabyte for safety. | |
| 286 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | |
| 287 LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data."; | |
| 288 return false; | |
| 289 } | |
| 290 | |
| 291 // Process lines until done. | |
| 292 std::istringstream topIn(output, std::istringstream::in); | |
| 293 std::string line; | |
| 294 while (std::getline(topIn, line)) { | |
| 295 std::istringstream in(line, std::istringstream::in); | |
| 296 | |
| 297 // Try to read the PID. | |
| 298 pid_t pid; | |
| 299 in >> pid; | |
| 300 if (in.fail()) | |
| 301 continue; | |
| 302 | |
| 303 // Make sure that caller is interested in this process. | |
| 304 if (proc_info_entries.find(pid) == proc_info_entries.end()) | |
| 305 continue; | |
| 306 | |
| 307 uint64_t values[4]; | |
| 308 size_t i; | |
| 309 for (i = 0; i < arraysize(values); i++) { | |
| 310 in >> values[i]; | |
| 311 if (in.fail()) | |
| 312 break; | |
| 313 } | |
| 314 if (i != arraysize(values)) | |
| 315 continue; | |
| 316 | |
| 317 ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; | |
| 318 proc_info.rss = values[0]; | |
| 319 proc_info.rshrd = values[1]; | |
| 320 proc_info.rprvt = values[2]; | |
| 321 proc_info.vsize = values[3]; | |
| 322 // Record the process information. | |
| 323 proc_info_entries[proc_info.pid] = proc_info; | |
| 324 } | |
| 325 | |
| 326 return true; | |
| 327 } | |
| 328 | |
| 329 | |
| 330 bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) { | |
| 331 Reset(); | |
| 332 | |
| 333 // Nothing to do if no PIDs given. | |
| 334 if (pid_list.size() == 0) | |
| 335 return true; | |
| 336 if (pid_list.size() > kMaxPidListSize) { | |
| 337 // The spec says |pid_list| *must* not have more than this many entries. | |
| 338 NOTREACHED(); | |
| 339 return false; | |
| 340 } | |
| 341 | |
| 342 // Get basic process info from KERN_PROC. | |
| 343 for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); | |
| 344 it != pid_list.end(); ++it) { | |
| 345 ProcInfoEntry proc_info; | |
| 346 proc_info.pid = *it; | |
| 347 | |
| 348 kinfo_proc kinfo; | |
| 349 if (!GetKInfoForProcessID(&kinfo, *it)) { | |
| 350 return false; | |
| 351 } | |
| 352 | |
| 353 proc_info.ppid = kinfo.kp_eproc.e_ppid; | |
| 354 proc_info.uid = kinfo.kp_eproc.e_pcred.p_ruid; | |
| 355 proc_info.euid = kinfo.kp_eproc.e_ucred.cr_uid; | |
| 356 // Note, p_comm is truncated to 15 characters. | |
|
Mark Mentovai
2011/01/04 20:09:31
Really? 15 or 16? p_comm is a char[MAXCOMLEN + 1],
sail
2011/01/06 00:23:00
Ahh, you're right. Fixed.
| |
| 357 proc_info.command = kinfo.kp_proc.p_comm; | |
| 358 proc_info_entries_[*it] = proc_info; | |
| 359 } | |
| 360 | |
| 361 // Use KERN_PROCARGS to get the full executable name. This may fail if we | |
|
Mark Mentovai
2011/01/04 20:09:31
we?
sail
2011/01/06 00:23:00
Done.
| |
| 362 // don't have privileges to inspect that process. | |
| 363 for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); | |
| 364 it != pid_list.end(); ++it) { | |
| 365 char* exectuable_name = NULL; | |
| 366 if (GetExecutableNameForProcessID(&exectuable_name, *it)) { | |
| 367 ProcInfoEntry proc_info = proc_info_entries_[*it]; | |
| 368 proc_info.command = exectuable_name; | |
| 369 delete exectuable_name; | |
|
Mark Mentovai
2011/01/04 20:09:31
See? Doesn’t this suck?
sail
2011/01/06 00:23:00
Done.
| |
| 370 } | |
| 371 } | |
| 372 | |
| 373 // Get memory information using top. | |
| 374 bool memoryInfoSuccess = false; | |
|
Mark Mentovai
2011/01/04 20:09:31
memory_info_success, because of http://google-styl
sail
2011/01/06 00:23:00
Done.
| |
| 375 int32 major, minor, bugfix; | |
| 376 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); | |
| 377 if (major == 10 && minor == 5) | |
| 378 memoryInfoSuccess = GetProcessMemoryInfoUsingTop_10_5(proc_info_entries_); | |
| 379 else | |
| 380 memoryInfoSuccess = GetProcessMemoryInfoUsingTop(proc_info_entries_); | |
|
Mark Mentovai
2011/01/04 20:09:31
I wouldn’t even try this unless ((major == 10 && m
sail
2011/01/06 00:23:00
Done.
| |
| 381 | |
| 382 // If top didn't work then fallback to ps. | |
|
Mark Mentovai
2011/01/04 20:09:31
“Fall back” as a verb is two words.
sail
2011/01/06 00:23:00
Done.
| |
| 383 if (!memoryInfoSuccess) | |
| 384 memoryInfoSuccess = GetProcessMemoryInfoUsingPS(pid_list, | |
|
Mark Mentovai
2011/01/04 20:09:31
This needs {braces} because it’s a multi-line.
sail
2011/01/06 00:23:00
Done.
| |
| 385 proc_info_entries_); | |
| 386 | |
| 387 return memoryInfoSuccess; | |
| 388 } | |
| 389 | |
| 109 // Clear all the stored information. | 390 // Clear all the stored information. |
| 110 void ProcessInfoSnapshot::Reset() { | 391 void ProcessInfoSnapshot::Reset() { |
| 111 proc_info_entries_.clear(); | 392 proc_info_entries_.clear(); |
| 112 } | 393 } |
| 113 | 394 |
| 114 bool ProcessInfoSnapshot::GetProcInfo(int pid, | 395 bool ProcessInfoSnapshot::GetProcInfo(int pid, |
| 115 ProcInfoEntry* proc_info) const { | 396 ProcInfoEntry* proc_info) const { |
| 116 std::map<int,ProcInfoEntry>::const_iterator it = proc_info_entries_.find(pid); | 397 std::map<int,ProcInfoEntry>::const_iterator it = proc_info_entries_.find(pid); |
| 117 if (it == proc_info_entries_.end()) | 398 if (it == proc_info_entries_.end()) |
| 118 return false; | 399 return false; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 132 | 413 |
| 133 // Failure of |GetProcInfo()| is "normal", due to racing. | 414 // Failure of |GetProcInfo()| is "normal", due to racing. |
| 134 ProcInfoEntry proc_info; | 415 ProcInfoEntry proc_info; |
| 135 if (!GetProcInfo(pid, &proc_info)) { | 416 if (!GetProcInfo(pid, &proc_info)) { |
| 136 usage->priv = 0; | 417 usage->priv = 0; |
| 137 usage->mapped = 0; | 418 usage->mapped = 0; |
| 138 usage->image = 0; | 419 usage->image = 0; |
| 139 return false; | 420 return false; |
| 140 } | 421 } |
| 141 | 422 |
| 142 usage->priv = proc_info.vsize; | 423 usage->priv = proc_info.vsize / 1024; |
| 143 usage->mapped = 0; | 424 usage->mapped = 0; |
| 144 usage->image = 0; | 425 usage->image = 0; |
| 145 return true; | 426 return true; |
| 146 } | 427 } |
| 147 | 428 |
| 148 bool ProcessInfoSnapshot::GetWorkingSetKBytesOfPID( | 429 bool ProcessInfoSnapshot::GetWorkingSetKBytesOfPID( |
| 149 int pid, | 430 int pid, |
| 150 base::WorkingSetKBytes* ws_usage) const { | 431 base::WorkingSetKBytes* ws_usage) const { |
| 151 // Try to avoid crashing on a bug; stats aren't usually so crucial. | 432 // Try to avoid crashing on a bug; stats aren't usually so crucial. |
| 152 if (!ws_usage) { | 433 if (!ws_usage) { |
| 153 NOTREACHED(); | 434 NOTREACHED(); |
| 154 return false; | 435 return false; |
| 155 } | 436 } |
| 156 | 437 |
| 157 // Failure of |GetProcInfo()| is "normal", due to racing. | 438 // Failure of |GetProcInfo()| is "normal", due to racing. |
| 158 ProcInfoEntry proc_info; | 439 ProcInfoEntry proc_info; |
| 159 if (!GetProcInfo(pid, &proc_info)) { | 440 if (!GetProcInfo(pid, &proc_info)) { |
| 160 ws_usage->priv = 0; | 441 ws_usage->priv = 0; |
| 161 ws_usage->shareable = 0; | 442 ws_usage->shareable = 0; |
| 162 ws_usage->shared = 0; | 443 ws_usage->shared = 0; |
| 163 return false; | 444 return false; |
| 164 } | 445 } |
| 165 | 446 |
| 166 ws_usage->priv = 0; | 447 ws_usage->priv = proc_info.rprvt / 1024; |
| 167 ws_usage->shareable = proc_info.rss; | 448 ws_usage->shareable = proc_info.rss / 1024; |
| 168 ws_usage->shared = 0; | 449 ws_usage->shared = proc_info.rshrd / 1024; |
| 169 return true; | 450 return true; |
| 170 } | 451 } |
| OLD | NEW |