Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: chrome/browser/process_info_snapshot_mac.cc

Issue 6052005: Proposal: Use /usr/bin/top in about:memory... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698