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

Side by Side Diff: base/process_util_linux.cc

Issue 6385003: Properly order the cc files based off the h files in base/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 11 months 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
« no previous file with comments | « base/process_util.cc ('k') | base/weak_ptr.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/process_util.h" 5 #include "base/process_util.h"
6 6
7 #include <ctype.h> 7 #include <ctype.h>
8 #include <dirent.h> 8 #include <dirent.h>
9 #include <dlfcn.h> 9 #include <dlfcn.h>
10 #include <errno.h> 10 #include <errno.h>
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 cmd_line_file = cmd_line_file.Append("cmdline"); 61 cmd_line_file = cmd_line_file.Append("cmdline");
62 std::string cmd_line; 62 std::string cmd_line;
63 if (!file_util::ReadFileToString(cmd_line_file, &cmd_line)) 63 if (!file_util::ReadFileToString(cmd_line_file, &cmd_line))
64 return false; 64 return false;
65 std::string delimiters; 65 std::string delimiters;
66 delimiters.push_back('\0'); 66 delimiters.push_back('\0');
67 Tokenize(cmd_line, delimiters, proc_cmd_line_args); 67 Tokenize(cmd_line, delimiters, proc_cmd_line_args);
68 return true; 68 return true;
69 } 69 }
70 70
71 // Get the total CPU of a single process. Return value is number of jiffies
72 // on success or -1 on error.
73 int GetProcessCPU(pid_t pid) {
74 // Synchronously reading files in /proc is safe.
75 base::ThreadRestrictions::ScopedAllowIO allow_io;
76
77 // Use /proc/<pid>/task to find all threads and parse their /stat file.
78 FilePath path = FilePath(StringPrintf("/proc/%d/task/", pid));
79
80 DIR* dir = opendir(path.value().c_str());
81 if (!dir) {
82 PLOG(ERROR) << "opendir(" << path.value() << ")";
83 return -1;
84 }
85
86 int total_cpu = 0;
87 while (struct dirent* ent = readdir(dir)) {
88 if (ent->d_name[0] == '.')
89 continue;
90
91 FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat");
92 std::string stat;
93 if (file_util::ReadFileToString(stat_path, &stat)) {
94 int cpu = base::ParseProcStatCPU(stat);
95 if (cpu > 0)
96 total_cpu += cpu;
97 }
98 }
99 closedir(dir);
100
101 return total_cpu;
102 }
103
71 } // namespace 104 } // namespace
72 105
73 namespace base { 106 namespace base {
74 107
75 ProcessId GetParentProcessId(ProcessHandle process) { 108 ProcessId GetParentProcessId(ProcessHandle process) {
76 // Synchronously reading files in /proc is safe. 109 // Synchronously reading files in /proc is safe.
77 base::ThreadRestrictions::ScopedAllowIO allow_io; 110 base::ThreadRestrictions::ScopedAllowIO allow_io;
78 111
79 FilePath stat_file("/proc"); 112 FilePath stat_file("/proc");
80 stat_file = stat_file.Append(base::IntToString(process)); 113 stat_file = stat_file.Append(base::IntToString(process));
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 return true; 252 return true;
220 } 253 }
221 254
222 bool NamedProcessIterator::IncludeEntry() { 255 bool NamedProcessIterator::IncludeEntry() {
223 if (executable_name_ != entry().exe_file()) 256 if (executable_name_ != entry().exe_file())
224 return false; 257 return false;
225 return ProcessIterator::IncludeEntry(); 258 return ProcessIterator::IncludeEntry();
226 } 259 }
227 260
228 261
229 ProcessMetrics::ProcessMetrics(ProcessHandle process)
230 : process_(process),
231 last_time_(0),
232 last_system_time_(0),
233 last_cpu_(0) {
234 processor_count_ = base::SysInfo::NumberOfProcessors();
235 }
236
237 // static 262 // static
238 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { 263 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
239 return new ProcessMetrics(process); 264 return new ProcessMetrics(process);
240 } 265 }
241 266
242 // On linux, we return vsize. 267 // On linux, we return vsize.
243 size_t ProcessMetrics::GetPagefileUsage() const { 268 size_t ProcessMetrics::GetPagefileUsage() const {
244 std::vector<std::string> proc_stats; 269 std::vector<std::string> proc_stats;
245 if (!GetProcStats(process_, &proc_stats)) 270 if (!GetProcStats(process_, &proc_stats))
246 LOG(WARNING) << "Failed to get process stats."; 271 LOG(WARNING) << "Failed to get process stats.";
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 ws_usage->priv = private_kb; 417 ws_usage->priv = private_kb;
393 // Sharable is not calculated, as it does not provide interesting data. 418 // Sharable is not calculated, as it does not provide interesting data.
394 ws_usage->shareable = 0; 419 ws_usage->shareable = 0;
395 420
396 ws_usage->shared = 0; 421 ws_usage->shared = 0;
397 if (have_pss) 422 if (have_pss)
398 ws_usage->shared = pss_kb; 423 ws_usage->shared = pss_kb;
399 return true; 424 return true;
400 } 425 }
401 426
427 double ProcessMetrics::GetCPUUsage() {
428 // This queries the /proc-specific scaling factor which is
429 // conceptually the system hertz. To dump this value on another
430 // system, try
431 // od -t dL /proc/self/auxv
432 // and look for the number after 17 in the output; mine is
433 // 0000040 17 100 3 134512692
434 // which means the answer is 100.
435 // It may be the case that this value is always 100.
436 static const int kHertz = sysconf(_SC_CLK_TCK);
437
438 struct timeval now;
439 int retval = gettimeofday(&now, NULL);
440 if (retval)
441 return 0;
442 int64 time = TimeValToMicroseconds(now);
443
444 if (last_time_ == 0) {
445 // First call, just set the last values.
446 last_time_ = time;
447 last_cpu_ = GetProcessCPU(process_);
448 return 0;
449 }
450
451 int64 time_delta = time - last_time_;
452 DCHECK_NE(time_delta, 0);
453 if (time_delta == 0)
454 return 0;
455
456 int cpu = GetProcessCPU(process_);
457
458 // We have the number of jiffies in the time period. Convert to percentage.
459 // Note this means we will go *over* 100 in the case where multiple threads
460 // are together adding to more than one CPU's worth.
461 int percentage = 100 * (cpu - last_cpu_) /
462 (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
463
464 last_time_ = time;
465 last_cpu_ = cpu;
466
467 return percentage;
468 }
469
402 // To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING 470 // To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
403 // in your kernel configuration. 471 // in your kernel configuration.
404 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { 472 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
405 // Synchronously reading files in /proc is safe. 473 // Synchronously reading files in /proc is safe.
406 base::ThreadRestrictions::ScopedAllowIO allow_io; 474 base::ThreadRestrictions::ScopedAllowIO allow_io;
407 475
408 std::string proc_io_contents; 476 std::string proc_io_contents;
409 FilePath io_file("/proc"); 477 FilePath io_file("/proc");
410 io_file = io_file.Append(base::IntToString(process_)); 478 io_file = io_file.Append(base::IntToString(process_));
411 io_file = io_file.Append("io"); 479 io_file = io_file.Append("io");
(...skipping 27 matching lines...) Expand all
439 base::StringToInt64(tokenizer.token(), 507 base::StringToInt64(tokenizer.token(),
440 reinterpret_cast<int64*>(&(*io_counters).WriteTransferCount)); 508 reinterpret_cast<int64*>(&(*io_counters).WriteTransferCount));
441 } 509 }
442 state = KEY_NAME; 510 state = KEY_NAME;
443 break; 511 break;
444 } 512 }
445 } 513 }
446 return true; 514 return true;
447 } 515 }
448 516
517 ProcessMetrics::ProcessMetrics(ProcessHandle process)
518 : process_(process),
519 last_time_(0),
520 last_system_time_(0),
521 last_cpu_(0) {
522 processor_count_ = base::SysInfo::NumberOfProcessors();
523 }
524
449 525
450 // Exposed for testing. 526 // Exposed for testing.
451 int ParseProcStatCPU(const std::string& input) { 527 int ParseProcStatCPU(const std::string& input) {
452 // /proc/<pid>/stat contains the process name in parens. In case the 528 // /proc/<pid>/stat contains the process name in parens. In case the
453 // process name itself contains parens, skip past them. 529 // process name itself contains parens, skip past them.
454 std::string::size_type rparen = input.rfind(')'); 530 std::string::size_type rparen = input.rfind(')');
455 if (rparen == std::string::npos) 531 if (rparen == std::string::npos)
456 return -1; 532 return -1;
457 533
458 // From here, we expect a bunch of space-separated fields, where the 534 // From here, we expect a bunch of space-separated fields, where the
459 // 0-indexed 11th and 12th are utime and stime. On two different machines 535 // 0-indexed 11th and 12th are utime and stime. On two different machines
460 // I found 42 and 39 fields, so let's just expect the ones we need. 536 // I found 42 and 39 fields, so let's just expect the ones we need.
461 std::vector<std::string> fields; 537 std::vector<std::string> fields;
462 base::SplitString(input.substr(rparen + 2), ' ', &fields); 538 base::SplitString(input.substr(rparen + 2), ' ', &fields);
463 if (fields.size() < 13) 539 if (fields.size() < 13)
464 return -1; // Output not in the format we expect. 540 return -1; // Output not in the format we expect.
465 541
466 int fields11, fields12; 542 int fields11, fields12;
467 base::StringToInt(fields[11], &fields11); 543 base::StringToInt(fields[11], &fields11);
468 base::StringToInt(fields[12], &fields12); 544 base::StringToInt(fields[12], &fields12);
469 return fields11 + fields12; 545 return fields11 + fields12;
470 } 546 }
471 547
472 // Get the total CPU of a single process. Return value is number of jiffies
473 // on success or -1 on error.
474 static int GetProcessCPU(pid_t pid) {
475 // Synchronously reading files in /proc is safe.
476 base::ThreadRestrictions::ScopedAllowIO allow_io;
477
478 // Use /proc/<pid>/task to find all threads and parse their /stat file.
479 FilePath path = FilePath(StringPrintf("/proc/%d/task/", pid));
480
481 DIR* dir = opendir(path.value().c_str());
482 if (!dir) {
483 PLOG(ERROR) << "opendir(" << path.value() << ")";
484 return -1;
485 }
486
487 int total_cpu = 0;
488 while (struct dirent* ent = readdir(dir)) {
489 if (ent->d_name[0] == '.')
490 continue;
491
492 FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat");
493 std::string stat;
494 if (file_util::ReadFileToString(stat_path, &stat)) {
495 int cpu = ParseProcStatCPU(stat);
496 if (cpu > 0)
497 total_cpu += cpu;
498 }
499 }
500 closedir(dir);
501
502 return total_cpu;
503 }
504
505 double ProcessMetrics::GetCPUUsage() {
506 // This queries the /proc-specific scaling factor which is
507 // conceptually the system hertz. To dump this value on another
508 // system, try
509 // od -t dL /proc/self/auxv
510 // and look for the number after 17 in the output; mine is
511 // 0000040 17 100 3 134512692
512 // which means the answer is 100.
513 // It may be the case that this value is always 100.
514 static const int kHertz = sysconf(_SC_CLK_TCK);
515
516 struct timeval now;
517 int retval = gettimeofday(&now, NULL);
518 if (retval)
519 return 0;
520 int64 time = TimeValToMicroseconds(now);
521
522 if (last_time_ == 0) {
523 // First call, just set the last values.
524 last_time_ = time;
525 last_cpu_ = GetProcessCPU(process_);
526 return 0;
527 }
528
529 int64 time_delta = time - last_time_;
530 DCHECK_NE(time_delta, 0);
531 if (time_delta == 0)
532 return 0;
533
534 int cpu = GetProcessCPU(process_);
535
536 // We have the number of jiffies in the time period. Convert to percentage.
537 // Note this means we will go *over* 100 in the case where multiple threads
538 // are together adding to more than one CPU's worth.
539 int percentage = 100 * (cpu - last_cpu_) /
540 (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
541
542 last_time_ = time;
543 last_cpu_ = cpu;
544
545 return percentage;
546 }
547
548 namespace { 548 namespace {
549 549
550 // The format of /proc/meminfo is: 550 // The format of /proc/meminfo is:
551 // 551 //
552 // MemTotal: 8235324 kB 552 // MemTotal: 8235324 kB
553 // MemFree: 1628304 kB 553 // MemFree: 1628304 kB
554 // Buffers: 429596 kB 554 // Buffers: 429596 kB
555 // Cached: 4728232 kB 555 // Cached: 4728232 kB
556 // ... 556 // ...
557 const size_t kMemTotalIndex = 1; 557 const size_t kMemTotalIndex = 1;
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 706
707 if (!file_util::PathExists(oom_adj)) 707 if (!file_util::PathExists(oom_adj))
708 return false; 708 return false;
709 709
710 std::string score_str = base::IntToString(score); 710 std::string score_str = base::IntToString(score);
711 return (static_cast<int>(score_str.length()) == 711 return (static_cast<int>(score_str.length()) ==
712 file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length())); 712 file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length()));
713 } 713 }
714 714
715 } // namespace base 715 } // namespace base
OLDNEW
« no previous file with comments | « base/process_util.cc ('k') | base/weak_ptr.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698