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 PLOG(ERROR) << "opendir(" << path.value() << ")"; | 87 DPLOG(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 LOG(WARNING) << "Failed to get process stats."; | 276 DLOG(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 LOG(WARNING) << "Failed to get process stats."; | 290 DLOG(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 LOG(WARNING) << "Failed to get process stats."; | 304 DLOG(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 LOG(WARNING) << "Failed to get process stats."; | 318 DLOG(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 LOG(WARNING) << "Failed to open /proc/meminfo."; | 579 DLOG(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 LOG(WARNING) << "Failed to parse /proc/meminfo. Only found " << | 586 DLOG(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 VLOG(1) << "Adjusting oom_score_adj of " << process << " to " << score_str; | 755 DVLOG(1) << "Adjusting oom_score_adj of " << process << " to " |
| 756 << score_str; |
756 int score_len = static_cast<int>(score_str.length()); | 757 int score_len = static_cast<int>(score_str.length()); |
757 return (score_len == file_util::WriteFile(oom_file, | 758 return (score_len == file_util::WriteFile(oom_file, |
758 score_str.c_str(), | 759 score_str.c_str(), |
759 score_len)); | 760 score_len)); |
760 } | 761 } |
761 | 762 |
762 // If the oom_score_adj file doesn't exist, then we write the old | 763 // If the oom_score_adj file doesn't exist, then we write the old |
763 // style file and translate the oom_adj score to the range 0-15. | 764 // style file and translate the oom_adj score to the range 0-15. |
764 oom_file = oom_path.AppendASCII("oom_adj"); | 765 oom_file = oom_path.AppendASCII("oom_adj"); |
765 if (file_util::PathExists(oom_file)) { | 766 if (file_util::PathExists(oom_file)) { |
766 std::string score_str = base::IntToString( | 767 std::string score_str = base::IntToString( |
767 score * kMaxOldOomScore / kMaxOomScore); | 768 score * kMaxOldOomScore / kMaxOomScore); |
768 VLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str; | 769 DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str; |
769 int score_len = static_cast<int>(score_str.length()); | 770 int score_len = static_cast<int>(score_str.length()); |
770 return (score_len == file_util::WriteFile(oom_file, | 771 return (score_len == file_util::WriteFile(oom_file, |
771 score_str.c_str(), | 772 score_str.c_str(), |
772 score_len)); | 773 score_len)); |
773 } | 774 } |
774 | 775 |
775 return false; | 776 return false; |
776 } | 777 } |
777 | 778 |
778 } // namespace base | 779 } // namespace base |
OLD | NEW |