summaryrefslogtreecommitdiff
path: root/chromium/base/process/process_metrics_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/process/process_metrics_linux.cc')
-rw-r--r--chromium/base/process/process_metrics_linux.cc75
1 files changed, 56 insertions, 19 deletions
diff --git a/chromium/base/process/process_metrics_linux.cc b/chromium/base/process/process_metrics_linux.cc
index 7ffccec2b3e..99bc54bc32b 100644
--- a/chromium/base/process/process_metrics_linux.cc
+++ b/chromium/base/process/process_metrics_linux.cc
@@ -18,6 +18,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
#include "base/optional.h"
#include "base/process/internal_linux.h"
#include "base/process/process_metrics_iocounters.h"
@@ -60,13 +61,9 @@ bool ReadProcFileToTrimmedStringPairs(pid_t pid,
StringPiece filename,
StringPairs* key_value_pairs) {
std::string status_data;
- {
- // Synchronously reading files in /proc does not hit the disk.
- ThreadRestrictions::ScopedAllowIO allow_io;
- FilePath status_file = internal::GetProcPidDir(pid).Append(filename);
- if (!ReadFileToString(status_file, &status_data))
- return false;
- }
+ FilePath status_file = internal::GetProcPidDir(pid).Append(filename);
+ if (!internal::ReadProcFile(status_file, &status_data))
+ return false;
SplitStringIntoKeyValuePairs(status_data, ':', '\n', key_value_pairs);
TrimKeyValuePairs(key_value_pairs);
return true;
@@ -130,6 +127,13 @@ bool ReadProcStatusAndGetFieldAsUint64(pid_t pid,
}
#endif // defined(OS_LINUX) || defined(OS_AIX)
+// Get the total CPU from a proc stat buffer. Return value is number of jiffies
+// on success or 0 if parsing failed.
+int64_t ParseTotalCPUTimeFromStats(const std::vector<std::string>& proc_stats) {
+ return internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME) +
+ internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
+}
+
// Get the total CPU of a single process. Return value is number of jiffies
// on success or -1 on error.
int64_t GetProcessCPU(pid_t pid) {
@@ -140,11 +144,7 @@ int64_t GetProcessCPU(pid_t pid) {
return -1;
}
- int64_t total_cpu =
- internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME) +
- internal::GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
-
- return total_cpu;
+ return ParseTotalCPUTimeFromStats(proc_stats);
}
#if defined(OS_CHROMEOS)
@@ -175,7 +175,7 @@ void ReadChromeOSGraphicsMemory(SystemMemoryInfoKB* meminfo) {
// Incorporate Mali graphics memory if present.
FilePath mali_memory_file("/sys/class/misc/mali0/device/memory");
std::string mali_memory_data;
- if (ReadFileToString(mali_memory_file, &mali_memory_data)) {
+ if (ReadFileToStringNonBlocking(mali_memory_file, &mali_memory_data)) {
long long mali_size = -1;
int num_res = sscanf(mali_memory_data.c_str(), "%lld bytes", &mali_size);
if (num_res == 1)
@@ -202,6 +202,43 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
return internal::ClockTicksToTimeDelta(GetProcessCPU(process_));
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(
+ CPUUsagePerThread& cpu_per_thread) {
+ cpu_per_thread.clear();
+
+ // Iterate through the different threads tracked in /proc/<pid>/task.
+ FilePath fd_path = internal::GetProcPidDir(process_).Append("task");
+
+ DirReaderPosix dir_reader(fd_path.value().c_str());
+ if (!dir_reader.IsValid())
+ return false;
+
+ for (; dir_reader.Next();) {
+ const char* tid_str = dir_reader.name();
+ if (strcmp(tid_str, ".") == 0 || strcmp(tid_str, "..") == 0)
+ continue;
+
+ PlatformThreadId tid;
+ if (!StringToInt(tid_str, &tid))
+ continue;
+
+ FilePath thread_stat_path = fd_path.Append(tid_str).Append("stat");
+
+ std::string buffer;
+ std::vector<std::string> proc_stats;
+ if (!internal::ReadProcFile(thread_stat_path, &buffer) ||
+ !internal::ParseProcStats(buffer, &proc_stats)) {
+ continue;
+ }
+
+ TimeDelta thread_time =
+ internal::ClockTicksToTimeDelta(ParseTotalCPUTimeFromStats(proc_stats));
+ cpu_per_thread.emplace_back(tid, thread_time);
+ }
+
+ return !cpu_per_thread.empty();
+}
+
// For the /proc/self/io file to exist, the Linux kernel must have
// CONFIG_TASK_IO_ACCOUNTING enabled.
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
@@ -280,7 +317,7 @@ int ProcessMetrics::GetOpenFdSoftLimit() const {
FilePath fd_path = internal::GetProcPidDir(process_).Append("limits");
std::string limits_contents;
- if (!ReadFileToString(fd_path, &limits_contents))
+ if (!ReadFileToStringNonBlocking(fd_path, &limits_contents))
return -1;
for (const auto& line : SplitStringPiece(
@@ -556,7 +593,7 @@ bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
// Used memory is: total - free - buffers - caches
FilePath meminfo_file("/proc/meminfo");
std::string meminfo_data;
- if (!ReadFileToString(meminfo_file, &meminfo_data)) {
+ if (!ReadFileToStringNonBlocking(meminfo_file, &meminfo_data)) {
DLOG(WARNING) << "Failed to open " << meminfo_file.value();
return false;
}
@@ -587,7 +624,7 @@ bool GetVmStatInfo(VmStatInfo* vmstat) {
FilePath vmstat_file("/proc/vmstat");
std::string vmstat_data;
- if (!ReadFileToString(vmstat_file, &vmstat_data)) {
+ if (!ReadFileToStringNonBlocking(vmstat_file, &vmstat_data)) {
DLOG(WARNING) << "Failed to open " << vmstat_file.value();
return false;
}
@@ -666,7 +703,7 @@ bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) {
FilePath diskinfo_file("/proc/diskstats");
std::string diskinfo_data;
- if (!ReadFileToString(diskinfo_file, &diskinfo_data)) {
+ if (!ReadFileToStringNonBlocking(diskinfo_file, &diskinfo_data)) {
DLOG(WARNING) << "Failed to open " << diskinfo_file.value();
return false;
}
@@ -866,7 +903,7 @@ bool GetSwapInfoImpl(SwapInfo* swap_info) {
}
std::string mm_stat_data;
- if (!ReadFileToString(zram_mm_stat_file, &mm_stat_data)) {
+ if (!ReadFileToStringNonBlocking(zram_mm_stat_file, &mm_stat_data)) {
DLOG(WARNING) << "Failed to open " << zram_mm_stat_file.value();
return false;
}
@@ -879,7 +916,7 @@ bool GetSwapInfoImpl(SwapInfo* swap_info) {
FilePath zram_stat_file("/sys/block/zram0/stat");
std::string stat_data;
- if (!ReadFileToString(zram_stat_file, &stat_data)) {
+ if (!ReadFileToStringNonBlocking(zram_stat_file, &stat_data)) {
DLOG(WARNING) << "Failed to open " << zram_stat_file.value();
return false;
}