summaryrefslogtreecommitdiff
path: root/chromium/base/process
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/base/process
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/base/process')
-rw-r--r--chromium/base/process/internal_linux.cc2
-rw-r--r--chromium/base/process/internal_linux.h5
-rw-r--r--chromium/base/process/kill_fuchsia.cc1
-rw-r--r--chromium/base/process/kill_win.cc1
-rw-r--r--chromium/base/process/launch_mac.cc2
-rw-r--r--chromium/base/process/launch_posix.cc2
-rw-r--r--chromium/base/process/memory_linux.cc6
-rw-r--r--chromium/base/process/process_handle.cc2
-rw-r--r--chromium/base/process/process_info_win.cc1
-rw-r--r--chromium/base/process/process_iterator_linux.cc1
-rw-r--r--chromium/base/process/process_metrics.h14
-rw-r--r--chromium/base/process/process_metrics_freebsd.cc5
-rw-r--r--chromium/base/process/process_metrics_fuchsia.cc8
-rw-r--r--chromium/base/process/process_metrics_ios.cc5
-rw-r--r--chromium/base/process/process_metrics_linux.cc75
-rw-r--r--chromium/base/process/process_metrics_mac.cc5
-rw-r--r--chromium/base/process/process_metrics_openbsd.cc5
-rw-r--r--chromium/base/process/process_metrics_unittest.cc69
-rw-r--r--chromium/base/process/process_metrics_win.cc5
19 files changed, 187 insertions, 27 deletions
diff --git a/chromium/base/process/internal_linux.cc b/chromium/base/process/internal_linux.cc
index 35b491738af..41cae833a24 100644
--- a/chromium/base/process/internal_linux.cc
+++ b/chromium/base/process/internal_linux.cc
@@ -13,6 +13,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
+#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -56,6 +57,7 @@ pid_t ProcDirSlotToPid(const char* d_name) {
}
bool ReadProcFile(const FilePath& file, std::string* buffer) {
+ DCHECK(FilePath(kProcDir).IsParent(file));
buffer->clear();
// Synchronously reading files in /proc is safe.
ThreadRestrictions::ScopedAllowIO allow_io;
diff --git a/chromium/base/process/internal_linux.h b/chromium/base/process/internal_linux.h
index d8904fd1102..dd6657ac795 100644
--- a/chromium/base/process/internal_linux.h
+++ b/chromium/base/process/internal_linux.h
@@ -30,6 +30,11 @@ extern const char kStatFile[];
// Returns a FilePath to "/proc/pid".
base::FilePath GetProcPidDir(pid_t pid);
+// Reads a file from /proc into a string. This is allowed on any thread as
+// reading from /proc does not hit the disk. Returns true if the file can be
+// read and is non-empty.
+bool ReadProcFile(const FilePath& file, std::string* buffer);
+
// Take a /proc directory entry named |d_name|, and if it is the directory for
// a process, convert it to a pid_t.
// Returns 0 on failure.
diff --git a/chromium/base/process/kill_fuchsia.cc b/chromium/base/process/kill_fuchsia.cc
index 2684a14756d..1b7bbd6a283 100644
--- a/chromium/base/process/kill_fuchsia.cc
+++ b/chromium/base/process/kill_fuchsia.cc
@@ -6,6 +6,7 @@
#include <zircon/syscalls.h>
+#include "base/logging.h"
#include "base/process/process_iterator.h"
#include "base/task/post_task.h"
#include "base/threading/platform_thread.h"
diff --git a/chromium/base/process/kill_win.cc b/chromium/base/process/kill_win.cc
index 3b85dea1cd4..61e8ed5c86c 100644
--- a/chromium/base/process/kill_win.cc
+++ b/chromium/base/process/kill_win.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/notreached.h"
#include "base/process/memory.h"
#include "base/process/process_iterator.h"
diff --git a/chromium/base/process/launch_mac.cc b/chromium/base/process/launch_mac.cc
index 6fc6ba115fb..9e523d39181 100644
--- a/chromium/base/process/launch_mac.cc
+++ b/chromium/base/process/launch_mac.cc
@@ -19,7 +19,7 @@
#include "base/process/environment_internal.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_restrictions.h"
-#include "base/trace_event/trace_event.h"
+#include "base/trace_event/base_tracing.h"
extern "C" {
// Changes the current thread's directory to a path or directory file
diff --git a/chromium/base/process/launch_posix.cc b/chromium/base/process/launch_posix.cc
index 9b7573fdc65..8ad7aa154fa 100644
--- a/chromium/base/process/launch_posix.cc
+++ b/chromium/base/process/launch_posix.cc
@@ -45,7 +45,7 @@
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
+#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#if defined(OS_LINUX) || defined(OS_AIX)
diff --git a/chromium/base/process/memory_linux.cc b/chromium/base/process/memory_linux.cc
index 6a6091a6047..ac8ffe1c243 100644
--- a/chromium/base/process/memory_linux.cc
+++ b/chromium/base/process/memory_linux.cc
@@ -132,11 +132,11 @@ bool UncheckedMalloc(size_t size, void** result) {
#if BUILDFLAG(USE_ALLOCATOR_SHIM)
*result = allocator::UncheckedAlloc(size);
#elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || \
- (!defined(LIBC_GLIBC) && !defined(USE_TCMALLOC))
+ (!defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC))
*result = malloc(size);
-#elif defined(LIBC_GLIBC) && !defined(USE_TCMALLOC)
+#elif defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC)
*result = __libc_malloc(size);
-#elif defined(USE_TCMALLOC)
+#elif BUILDFLAG(USE_TCMALLOC)
*result = tc_malloc_skip_new_handler(size);
#endif
return *result != nullptr;
diff --git a/chromium/base/process/process_handle.cc b/chromium/base/process/process_handle.cc
index 7b130b40b14..fcaa129126c 100644
--- a/chromium/base/process/process_handle.cc
+++ b/chromium/base/process/process_handle.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <ostream>
+
#include "base/check.h"
#include "build/build_config.h"
diff --git a/chromium/base/process/process_info_win.cc b/chromium/base/process/process_info_win.cc
index 05d0f21a930..594fd1d112d 100644
--- a/chromium/base/process/process_info_win.cc
+++ b/chromium/base/process/process_info_win.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
#include "base/time/time.h"
#include "base/win/scoped_handle.h"
diff --git a/chromium/base/process/process_iterator_linux.cc b/chromium/base/process/process_iterator_linux.cc
index 39313b2bb55..fd1821a2670 100644
--- a/chromium/base/process/process_iterator_linux.cc
+++ b/chromium/base/process/process_iterator_linux.cc
@@ -8,6 +8,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
+#include "base/notreached.h"
#include "base/process/internal_linux.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
diff --git a/chromium/base/process/process_metrics.h b/chromium/base/process/process_metrics.h
index 2b7cfe14f73..be23db0f928 100644
--- a/chromium/base/process/process_metrics.h
+++ b/chromium/base/process/process_metrics.h
@@ -13,11 +13,14 @@
#include <memory>
#include <string>
+#include <utility>
+#include <vector>
#include "base/base_export.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/process/process_handle.h"
+#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -118,6 +121,17 @@ class BASE_EXPORT ProcessMetrics {
// will result in a time delta of 2 seconds/per 1 wall-clock second.
TimeDelta GetCumulativeCPUUsage();
+ // Emits the cumulative CPU usage for all currently active threads since they
+ // were started into the output parameter (replacing its current contents).
+ // Threads that have already terminated will not be reported. Thus, the sum of
+ // these times may not equal the value returned by GetCumulativeCPUUsage().
+ // Returns false on failure. We return the usage via an output parameter to
+ // allow reuse of CPUUsagePerThread's std::vector by the caller, e.g. to avoid
+ // allocations between repeated calls to method.
+ // NOTE: Currently only supported on Linux/Android.
+ using CPUUsagePerThread = std::vector<std::pair<PlatformThreadId, TimeDelta>>;
+ bool GetCumulativeCPUUsagePerThread(CPUUsagePerThread&);
+
// Returns the number of average idle cpu wakeups per second since the last
// call.
int GetIdleWakeupsPerSecond();
diff --git a/chromium/base/process/process_metrics_freebsd.cc b/chromium/base/process/process_metrics_freebsd.cc
index a552c033dd8..3fc3160cc1e 100644
--- a/chromium/base/process/process_metrics_freebsd.cc
+++ b/chromium/base/process/process_metrics_freebsd.cc
@@ -42,6 +42,11 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
return TimeDelta();
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(CPUUsagePerThread&) {
+ NOTREACHED();
+ return false;
+}
+
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return false;
}
diff --git a/chromium/base/process/process_metrics_fuchsia.cc b/chromium/base/process/process_metrics_fuchsia.cc
index 3c7d14cd84e..fc9b0c46eee 100644
--- a/chromium/base/process/process_metrics_fuchsia.cc
+++ b/chromium/base/process/process_metrics_fuchsia.cc
@@ -6,6 +6,8 @@
#include <lib/fdio/limits.h>
+#include "base/notreached.h"
+
namespace base {
size_t GetMaxFds() {
@@ -35,6 +37,12 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
return TimeDelta();
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(CPUUsagePerThread&) {
+ // TODO(https://crbug.com/926581).
+ NOTIMPLEMENTED();
+ return false;
+}
+
bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
// TODO(https://crbug.com/926581).
return false;
diff --git a/chromium/base/process/process_metrics_ios.cc b/chromium/base/process/process_metrics_ios.cc
index ae36b7d4fc6..6e466801f3b 100644
--- a/chromium/base/process/process_metrics_ios.cc
+++ b/chromium/base/process/process_metrics_ios.cc
@@ -32,6 +32,11 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
return TimeDelta();
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(CPUUsagePerThread&) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
size_t GetMaxFds() {
static const rlim_t kSystemDefaultMaxFds = 256;
rlim_t max_fds;
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;
}
diff --git a/chromium/base/process/process_metrics_mac.cc b/chromium/base/process/process_metrics_mac.cc
index d0f35471cb7..33b10d8563f 100644
--- a/chromium/base/process/process_metrics_mac.cc
+++ b/chromium/base/process/process_metrics_mac.cc
@@ -154,6 +154,11 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
return TimeDelta::FromMicroseconds(TimeValToMicroseconds(task_timeval));
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(CPUUsagePerThread&) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
int ProcessMetrics::GetPackageIdleWakeupsPerSecond() {
mach_port_t task = TaskForPid(process_);
task_power_info power_info_data;
diff --git a/chromium/base/process/process_metrics_openbsd.cc b/chromium/base/process/process_metrics_openbsd.cc
index 0fb41b6ff3a..0399f8d4441 100644
--- a/chromium/base/process/process_metrics_openbsd.cc
+++ b/chromium/base/process/process_metrics_openbsd.cc
@@ -64,6 +64,11 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
return TimeDelta();
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(CPUUsagePerThread&) {
+ NOTREACHED();
+ return false;
+}
+
ProcessMetrics::ProcessMetrics(ProcessHandle process)
: process_(process),
last_cpu_(0) {}
diff --git a/chromium/base/process/process_metrics_unittest.cc b/chromium/base/process/process_metrics_unittest.cc
index 808a7be09d0..c269a4713f7 100644
--- a/chromium/base/process/process_metrics_unittest.cc
+++ b/chromium/base/process/process_metrics_unittest.cc
@@ -35,7 +35,8 @@
namespace base {
namespace debug {
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) || \
+ defined(OS_ANDROID)
namespace {
void BusyWork(std::vector<std::string>* vec) {
@@ -47,7 +48,8 @@ void BusyWork(std::vector<std::string>* vec) {
}
} // namespace
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) ||
+ // defined(OS_ANDROID)
// Tests for SystemMetrics.
// Exists as a class so it can be a friend of SystemMetrics.
@@ -376,7 +378,7 @@ TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
}
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
#if defined(OS_CHROMEOS)
TEST_F(SystemMetricsTest, ParseZramMmStat) {
@@ -646,6 +648,7 @@ TEST(ProcessMetricsTest, GetOpenFdCount) {
#endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
#if defined(OS_ANDROID) || defined(OS_LINUX)
+
TEST(ProcessMetricsTestLinux, GetPageFaultCounts) {
std::unique_ptr<base::ProcessMetrics> process_metrics(
base::ProcessMetrics::CreateProcessMetrics(
@@ -676,6 +679,66 @@ TEST(ProcessMetricsTestLinux, GetPageFaultCounts) {
ASSERT_GT(counts_after.minor, counts.minor);
ASSERT_GE(counts_after.major, counts.major);
}
+
+TEST(ProcessMetricsTestLinux, GetCumulativeCPUUsagePerThread) {
+ ProcessHandle handle = GetCurrentProcessHandle();
+ std::unique_ptr<ProcessMetrics> metrics(
+ ProcessMetrics::CreateProcessMetrics(handle));
+
+ Thread thread1("thread1");
+ thread1.StartAndWaitForTesting();
+ ASSERT_TRUE(thread1.IsRunning());
+
+ std::vector<std::string> vec1;
+ thread1.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec1));
+
+ ProcessMetrics::CPUUsagePerThread prev_thread_times;
+ EXPECT_TRUE(metrics->GetCumulativeCPUUsagePerThread(prev_thread_times));
+
+ // Should have at least the test runner thread and the thread spawned above.
+ EXPECT_GE(prev_thread_times.size(), 2u);
+ EXPECT_TRUE(std::any_of(
+ prev_thread_times.begin(), prev_thread_times.end(),
+ [&thread1](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
+ return entry.first == thread1.GetThreadId();
+ }));
+ EXPECT_TRUE(std::any_of(
+ prev_thread_times.begin(), prev_thread_times.end(),
+ [](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
+ return entry.first == base::PlatformThread::CurrentId();
+ }));
+
+ for (const auto& entry : prev_thread_times) {
+ EXPECT_GE(entry.second, base::TimeDelta());
+ }
+
+ thread1.Stop();
+
+ ProcessMetrics::CPUUsagePerThread current_thread_times;
+ EXPECT_TRUE(metrics->GetCumulativeCPUUsagePerThread(current_thread_times));
+
+ // The stopped thread may still be reported until the kernel cleans it up.
+ EXPECT_GE(prev_thread_times.size(), 1u);
+ EXPECT_TRUE(std::any_of(
+ current_thread_times.begin(), current_thread_times.end(),
+ [](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
+ return entry.first == base::PlatformThread::CurrentId();
+ }));
+
+ // Reported times should not decrease.
+ for (const auto& entry : current_thread_times) {
+ auto prev_it = std::find_if(
+ prev_thread_times.begin(), prev_thread_times.end(),
+ [&entry](
+ const std::pair<PlatformThreadId, base::TimeDelta>& prev_entry) {
+ return entry.first == prev_entry.first;
+ });
+
+ if (prev_it != prev_thread_times.end())
+ EXPECT_GE(entry.second, prev_it->second);
+ }
+}
+
#endif // defined(OS_ANDROID) || defined(OS_LINUX)
#if defined(OS_WIN)
diff --git a/chromium/base/process/process_metrics_win.cc b/chromium/base/process/process_metrics_win.cc
index 5cf0943c654..3cd51852a33 100644
--- a/chromium/base/process/process_metrics_win.cc
+++ b/chromium/base/process/process_metrics_win.cc
@@ -162,6 +162,11 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
TimeDelta::FromFileTime(user_time);
}
+bool ProcessMetrics::GetCumulativeCPUUsagePerThread(CPUUsagePerThread&) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
if (!process_.IsValid())
return false;