| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // on success or -1 on error. | 77 // on success or -1 on error. |
| 78 int GetProcessCPU(pid_t pid) { | 78 int GetProcessCPU(pid_t pid) { |
| 79 // Synchronously reading files in /proc is safe. | 79 // Synchronously reading files in /proc is safe. |
| 80 base::ThreadRestrictions::ScopedAllowIO allow_io; | 80 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 81 | 81 |
| 82 // Use /proc/<pid>/task to find all threads and parse their /stat file. | 82 // Use /proc/<pid>/task to find all threads and parse their /stat file. |
| 83 FilePath path = FilePath(base::StringPrintf("/proc/%d/task/", pid)); | 83 FilePath path = FilePath(base::StringPrintf("/proc/%d/task/", pid)); |
| 84 | 84 |
| 85 DIR* dir = opendir(path.value().c_str()); | 85 DIR* dir = opendir(path.value().c_str()); |
| 86 if (!dir) { | 86 if (!dir) { |
| 87 DPLOG(ERROR) << "opendir(" << path.value() << ")"; | 87 PLOG(ERROR) << "opendir(" << path.value() << ")"; |
| 88 return -1; | 88 return -1; |
| 89 } | 89 } |
| 90 | 90 |
| 91 int total_cpu = 0; | 91 int total_cpu = 0; |
| 92 while (struct dirent* ent = readdir(dir)) { | 92 while (struct dirent* ent = readdir(dir)) { |
| 93 if (ent->d_name[0] == '.') | 93 if (ent->d_name[0] == '.') |
| 94 continue; | 94 continue; |
| 95 | 95 |
| 96 FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat"); | 96 FilePath stat_path = path.AppendASCII(ent->d_name).AppendASCII("stat"); |
| 97 std::string stat; | 97 std::string stat; |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 | 266 |
| 267 // static | 267 // static |
| 268 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { | 268 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { |
| 269 return new ProcessMetrics(process); | 269 return new ProcessMetrics(process); |
| 270 } | 270 } |
| 271 | 271 |
| 272 // On linux, we return vsize. | 272 // On linux, we return vsize. |
| 273 size_t ProcessMetrics::GetPagefileUsage() const { | 273 size_t ProcessMetrics::GetPagefileUsage() const { |
| 274 std::vector<std::string> proc_stats; | 274 std::vector<std::string> proc_stats; |
| 275 if (!GetProcStats(process_, &proc_stats)) | 275 if (!GetProcStats(process_, &proc_stats)) |
| 276 DLOG(WARNING) << "Failed to get process stats."; | 276 LOG(WARNING) << "Failed to get process stats."; |
| 277 const size_t kVmSize = 22; | 277 const size_t kVmSize = 22; |
| 278 if (proc_stats.size() > kVmSize) { | 278 if (proc_stats.size() > kVmSize) { |
| 279 int vm_size; | 279 int vm_size; |
| 280 base::StringToInt(proc_stats[kVmSize], &vm_size); | 280 base::StringToInt(proc_stats[kVmSize], &vm_size); |
| 281 return static_cast<size_t>(vm_size); | 281 return static_cast<size_t>(vm_size); |
| 282 } | 282 } |
| 283 return 0; | 283 return 0; |
| 284 } | 284 } |
| 285 | 285 |
| 286 // On linux, we return the high water mark of vsize. | 286 // On linux, we return the high water mark of vsize. |
| 287 size_t ProcessMetrics::GetPeakPagefileUsage() const { | 287 size_t ProcessMetrics::GetPeakPagefileUsage() const { |
| 288 std::vector<std::string> proc_stats; | 288 std::vector<std::string> proc_stats; |
| 289 if (!GetProcStats(process_, &proc_stats)) | 289 if (!GetProcStats(process_, &proc_stats)) |
| 290 DLOG(WARNING) << "Failed to get process stats."; | 290 LOG(WARNING) << "Failed to get process stats."; |
| 291 const size_t kVmPeak = 21; | 291 const size_t kVmPeak = 21; |
| 292 if (proc_stats.size() > kVmPeak) { | 292 if (proc_stats.size() > kVmPeak) { |
| 293 int vm_peak; | 293 int vm_peak; |
| 294 if (base::StringToInt(proc_stats[kVmPeak], &vm_peak)) | 294 if (base::StringToInt(proc_stats[kVmPeak], &vm_peak)) |
| 295 return vm_peak; | 295 return vm_peak; |
| 296 } | 296 } |
| 297 return 0; | 297 return 0; |
| 298 } | 298 } |
| 299 | 299 |
| 300 // On linux, we return RSS. | 300 // On linux, we return RSS. |
| 301 size_t ProcessMetrics::GetWorkingSetSize() const { | 301 size_t ProcessMetrics::GetWorkingSetSize() const { |
| 302 std::vector<std::string> proc_stats; | 302 std::vector<std::string> proc_stats; |
| 303 if (!GetProcStats(process_, &proc_stats)) | 303 if (!GetProcStats(process_, &proc_stats)) |
| 304 DLOG(WARNING) << "Failed to get process stats."; | 304 LOG(WARNING) << "Failed to get process stats."; |
| 305 const size_t kVmRss = 23; | 305 const size_t kVmRss = 23; |
| 306 if (proc_stats.size() > kVmRss) { | 306 if (proc_stats.size() > kVmRss) { |
| 307 int num_pages; | 307 int num_pages; |
| 308 if (base::StringToInt(proc_stats[kVmRss], &num_pages)) | 308 if (base::StringToInt(proc_stats[kVmRss], &num_pages)) |
| 309 return static_cast<size_t>(num_pages) * getpagesize(); | 309 return static_cast<size_t>(num_pages) * getpagesize(); |
| 310 } | 310 } |
| 311 return 0; | 311 return 0; |
| 312 } | 312 } |
| 313 | 313 |
| 314 // On linux, we return the high water mark of RSS. | 314 // On linux, we return the high water mark of RSS. |
| 315 size_t ProcessMetrics::GetPeakWorkingSetSize() const { | 315 size_t ProcessMetrics::GetPeakWorkingSetSize() const { |
| 316 std::vector<std::string> proc_stats; | 316 std::vector<std::string> proc_stats; |
| 317 if (!GetProcStats(process_, &proc_stats)) | 317 if (!GetProcStats(process_, &proc_stats)) |
| 318 DLOG(WARNING) << "Failed to get process stats."; | 318 LOG(WARNING) << "Failed to get process stats."; |
| 319 const size_t kVmHwm = 23; | 319 const size_t kVmHwm = 23; |
| 320 if (proc_stats.size() > kVmHwm) { | 320 if (proc_stats.size() > kVmHwm) { |
| 321 int num_pages; | 321 int num_pages; |
| 322 base::StringToInt(proc_stats[kVmHwm], &num_pages); | 322 base::StringToInt(proc_stats[kVmHwm], &num_pages); |
| 323 return static_cast<size_t>(num_pages) * getpagesize(); | 323 return static_cast<size_t>(num_pages) * getpagesize(); |
| 324 } | 324 } |
| 325 return 0; | 325 return 0; |
| 326 } | 326 } |
| 327 | 327 |
| 328 bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, | 328 bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 } // namespace | 569 } // namespace |
| 570 | 570 |
| 571 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { | 571 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { |
| 572 // Synchronously reading files in /proc is safe. | 572 // Synchronously reading files in /proc is safe. |
| 573 base::ThreadRestrictions::ScopedAllowIO allow_io; | 573 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 574 | 574 |
| 575 // Used memory is: total - free - buffers - caches | 575 // Used memory is: total - free - buffers - caches |
| 576 FilePath meminfo_file("/proc/meminfo"); | 576 FilePath meminfo_file("/proc/meminfo"); |
| 577 std::string meminfo_data; | 577 std::string meminfo_data; |
| 578 if (!file_util::ReadFileToString(meminfo_file, &meminfo_data)) { | 578 if (!file_util::ReadFileToString(meminfo_file, &meminfo_data)) { |
| 579 DLOG(WARNING) << "Failed to open /proc/meminfo."; | 579 LOG(WARNING) << "Failed to open /proc/meminfo."; |
| 580 return false; | 580 return false; |
| 581 } | 581 } |
| 582 std::vector<std::string> meminfo_fields; | 582 std::vector<std::string> meminfo_fields; |
| 583 SplitStringAlongWhitespace(meminfo_data, &meminfo_fields); | 583 SplitStringAlongWhitespace(meminfo_data, &meminfo_fields); |
| 584 | 584 |
| 585 if (meminfo_fields.size() < kMemCachedIndex) { | 585 if (meminfo_fields.size() < kMemCachedIndex) { |
| 586 DLOG(WARNING) << "Failed to parse /proc/meminfo. Only found " << | 586 LOG(WARNING) << "Failed to parse /proc/meminfo. Only found " << |
| 587 meminfo_fields.size() << " fields."; | 587 meminfo_fields.size() << " fields."; |
| 588 return false; | 588 return false; |
| 589 } | 589 } |
| 590 | 590 |
| 591 DCHECK_EQ(meminfo_fields[kMemTotalIndex-1], "MemTotal:"); | 591 DCHECK_EQ(meminfo_fields[kMemTotalIndex-1], "MemTotal:"); |
| 592 DCHECK_EQ(meminfo_fields[kMemFreeIndex-1], "MemFree:"); | 592 DCHECK_EQ(meminfo_fields[kMemFreeIndex-1], "MemFree:"); |
| 593 DCHECK_EQ(meminfo_fields[kMemBuffersIndex-1], "Buffers:"); | 593 DCHECK_EQ(meminfo_fields[kMemBuffersIndex-1], "Buffers:"); |
| 594 DCHECK_EQ(meminfo_fields[kMemCachedIndex-1], "Cached:"); | 594 DCHECK_EQ(meminfo_fields[kMemCachedIndex-1], "Cached:"); |
| 595 DCHECK_EQ(meminfo_fields[kMemActiveAnonIndex-1], "Active(anon):"); | 595 DCHECK_EQ(meminfo_fields[kMemActiveAnonIndex-1], "Active(anon):"); |
| 596 DCHECK_EQ(meminfo_fields[kMemInactiveAnonIndex-1], "Inactive(anon):"); | 596 DCHECK_EQ(meminfo_fields[kMemInactiveAnonIndex-1], "Inactive(anon):"); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 if (score < 0 || score > kMaxOomScore) | 745 if (score < 0 || score > kMaxOomScore) |
| 746 return false; | 746 return false; |
| 747 | 747 |
| 748 FilePath oom_path("/proc"); | 748 FilePath oom_path("/proc"); |
| 749 oom_path = oom_path.Append(base::Int64ToString(process)); | 749 oom_path = oom_path.Append(base::Int64ToString(process)); |
| 750 | 750 |
| 751 // Attempt to write the newer oom_score_adj file first. | 751 // Attempt to write the newer oom_score_adj file first. |
| 752 FilePath oom_file = oom_path.AppendASCII("oom_score_adj"); | 752 FilePath oom_file = oom_path.AppendASCII("oom_score_adj"); |
| 753 if (file_util::PathExists(oom_file)) { | 753 if (file_util::PathExists(oom_file)) { |
| 754 std::string score_str = base::IntToString(score); | 754 std::string score_str = base::IntToString(score); |
| 755 DVLOG(1) << "Adjusting oom_score_adj of " << process << " to " | 755 VLOG(1) << "Adjusting oom_score_adj of " << process << " to " << score_str; |
| 756 << score_str; | |
| 757 int score_len = static_cast<int>(score_str.length()); | 756 int score_len = static_cast<int>(score_str.length()); |
| 758 return (score_len == file_util::WriteFile(oom_file, | 757 return (score_len == file_util::WriteFile(oom_file, |
| 759 score_str.c_str(), | 758 score_str.c_str(), |
| 760 score_len)); | 759 score_len)); |
| 761 } | 760 } |
| 762 | 761 |
| 763 // If the oom_score_adj file doesn't exist, then we write the old | 762 // If the oom_score_adj file doesn't exist, then we write the old |
| 764 // style file and translate the oom_adj score to the range 0-15. | 763 // style file and translate the oom_adj score to the range 0-15. |
| 765 oom_file = oom_path.AppendASCII("oom_adj"); | 764 oom_file = oom_path.AppendASCII("oom_adj"); |
| 766 if (file_util::PathExists(oom_file)) { | 765 if (file_util::PathExists(oom_file)) { |
| 767 std::string score_str = base::IntToString( | 766 std::string score_str = base::IntToString( |
| 768 score * kMaxOldOomScore / kMaxOomScore); | 767 score * kMaxOldOomScore / kMaxOomScore); |
| 769 DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str; | 768 VLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str; |
| 770 int score_len = static_cast<int>(score_str.length()); | 769 int score_len = static_cast<int>(score_str.length()); |
| 771 return (score_len == file_util::WriteFile(oom_file, | 770 return (score_len == file_util::WriteFile(oom_file, |
| 772 score_str.c_str(), | 771 score_str.c_str(), |
| 773 score_len)); | 772 score_len)); |
| 774 } | 773 } |
| 775 | 774 |
| 776 return false; | 775 return false; |
| 777 } | 776 } |
| 778 | 777 |
| 779 } // namespace base | 778 } // namespace base |
| OLD | NEW |