[M108 Migration][VD] Support set time and time zone offset
[platform/framework/web/chromium-efl.git] / base / cpu.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/cpu.h"
6
7 #include <inttypes.h>
8 #include <limits.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <string.h>
12
13 #include <algorithm>
14 #include <sstream>
15 #include <utility>
16
17 #include "base/no_destructor.h"
18 #include "build/build_config.h"
19
20 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
21     BUILDFLAG(IS_AIX)
22 #include "base/containers/flat_set.h"
23 #include "base/files/file_util.h"
24 #include "base/format_macros.h"
25 #include "base/notreached.h"
26 #include "base/process/internal_linux.h"
27 #include "base/strings/string_number_conversions.h"
28 #include "base/strings/string_util.h"
29 #include "base/strings/stringprintf.h"
30 #include "base/system/sys_info.h"
31 #include "base/threading/thread_restrictions.h"
32 #endif
33
34 #if defined(ARCH_CPU_ARM_FAMILY) && \
35     (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
36 #include <asm/hwcap.h>
37 #include <sys/auxv.h>
38 #include "base/files/file_util.h"
39 #include "base/numerics/checked_math.h"
40 #include "base/ranges/algorithm.h"
41 #include "base/strings/string_split.h"
42 #include "base/strings/string_util.h"
43
44 // Temporary definitions until a new hwcap.h is pulled in everywhere.
45 // https://crbug.com/1265965
46 #ifndef HWCAP2_MTE
47 #define HWCAP2_MTE (1 << 18)
48 #define HWCAP2_BTI (1 << 17)
49 #endif
50
51 struct ProcCpuInfo {
52   std::string brand;
53   uint8_t implementer = 0;
54   uint32_t part_number = 0;
55 };
56 #endif
57
58 #if defined(ARCH_CPU_X86_FAMILY)
59 #if defined(COMPILER_MSVC)
60 #include <intrin.h>
61 #include <immintrin.h>  // For _xgetbv()
62 #endif
63 #endif
64
65 namespace base {
66
67 #if defined(ARCH_CPU_X86_FAMILY)
68 namespace internal {
69
70 X86ModelInfo ComputeX86FamilyAndModel(const std::string& vendor,
71                                       int signature) {
72   X86ModelInfo results;
73   results.family = (signature >> 8) & 0xf;
74   results.model = (signature >> 4) & 0xf;
75   results.ext_family = 0;
76   results.ext_model = 0;
77
78   // The "Intel 64 and IA-32 Architectures Developer's Manual: Vol. 2A"
79   // specifies the Extended Model is defined only when the Base Family is
80   // 06h or 0Fh.
81   // The "AMD CPUID Specification" specifies that the Extended Model is
82   // defined only when Base Family is 0Fh.
83   // Both manuals define the display model as
84   // {ExtendedModel[3:0],BaseModel[3:0]} in that case.
85   if (results.family == 0xf ||
86       (results.family == 0x6 && vendor == "GenuineIntel")) {
87     results.ext_model = (signature >> 16) & 0xf;
88     results.model += results.ext_model << 4;
89   }
90   // Both the "Intel 64 and IA-32 Architectures Developer's Manual: Vol. 2A"
91   // and the "AMD CPUID Specification" specify that the Extended Family is
92   // defined only when the Base Family is 0Fh.
93   // Both manuals define the display family as {0000b,BaseFamily[3:0]} +
94   // ExtendedFamily[7:0] in that case.
95   if (results.family == 0xf) {
96     results.ext_family = (signature >> 20) & 0xff;
97     results.family += results.ext_family;
98   }
99
100   return results;
101 }
102
103 }  // namespace internal
104 #endif  // defined(ARCH_CPU_X86_FAMILY)
105
106 CPU::CPU(bool require_branding) {
107   Initialize(require_branding);
108 }
109 CPU::CPU() : CPU(true) {}
110 CPU::CPU(CPU&&) = default;
111
112 namespace {
113
114 #if defined(ARCH_CPU_X86_FAMILY)
115 #if !defined(COMPILER_MSVC)
116
117 #if defined(__pic__) && defined(__i386__)
118
119 void __cpuid(int cpu_info[4], int info_type) {
120   __asm__ volatile(
121       "mov %%ebx, %%edi\n"
122       "cpuid\n"
123       "xchg %%edi, %%ebx\n"
124       : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
125         "=d"(cpu_info[3])
126       : "a"(info_type), "c"(0));
127 }
128
129 #else
130
131 void __cpuid(int cpu_info[4], int info_type) {
132   __asm__ volatile("cpuid\n"
133                    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
134                      "=d"(cpu_info[3])
135                    : "a"(info_type), "c"(0));
136 }
137
138 #endif
139 #endif  // !defined(COMPILER_MSVC)
140
141 // xgetbv returns the value of an Intel Extended Control Register (XCR).
142 // Currently only XCR0 is defined by Intel so |xcr| should always be zero.
143 uint64_t xgetbv(uint32_t xcr) {
144 #if defined(COMPILER_MSVC)
145   return _xgetbv(xcr);
146 #else
147   uint32_t eax, edx;
148
149   __asm__ volatile (
150     "xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
151   return (static_cast<uint64_t>(edx) << 32) | eax;
152 #endif  // defined(COMPILER_MSVC)
153 }
154
155 #endif  // ARCH_CPU_X86_FAMILY
156
157 #if defined(ARCH_CPU_ARM_FAMILY) && \
158     (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
159 StringPairs::const_iterator FindFirstProcCpuKey(const StringPairs& pairs,
160                                                 StringPiece key) {
161   return ranges::find_if(pairs, [key](const StringPairs::value_type& pair) {
162     return TrimWhitespaceASCII(pair.first, base::TRIM_ALL) == key;
163   });
164 }
165
166 // Parses information about the ARM processor. Note that depending on the CPU
167 // package, processor configuration, and/or kernel version, this may only
168 // report information about the processor on which this thread is running. This
169 // can happen on heterogeneous-processor SoCs like Snapdragon 808, which has 4
170 // Cortex-A53 and 2 Cortex-A57. Unfortunately there is not a universally
171 // reliable way to examine the CPU part information for all cores.
172 const ProcCpuInfo& ParseProcCpu() {
173   static const NoDestructor<ProcCpuInfo> info([]() {
174     // This function finds the value from /proc/cpuinfo under the key "model
175     // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7
176     // and later for arm64) and is shown once per CPU. "Processor" is used in
177     // earler versions and is shown only once at the top of /proc/cpuinfo
178     // regardless of the number CPUs.
179     const char kModelNamePrefix[] = "model name";
180     const char kProcessorPrefix[] = "Processor";
181
182     std::string cpuinfo;
183     ReadFileToString(FilePath("/proc/cpuinfo"), &cpuinfo);
184     DCHECK(!cpuinfo.empty());
185
186     ProcCpuInfo info;
187
188     StringPairs pairs;
189     if (!SplitStringIntoKeyValuePairs(cpuinfo, ':', '\n', &pairs)) {
190       NOTREACHED();
191       return info;
192     }
193
194     auto model_name = FindFirstProcCpuKey(pairs, kModelNamePrefix);
195     if (model_name == pairs.end())
196       model_name = FindFirstProcCpuKey(pairs, kProcessorPrefix);
197     if (model_name != pairs.end()) {
198       info.brand =
199           std::string(TrimWhitespaceASCII(model_name->second, TRIM_ALL));
200     }
201
202     auto implementer_string = FindFirstProcCpuKey(pairs, "CPU implementer");
203     if (implementer_string != pairs.end()) {
204       // HexStringToUInt() handles the leading whitespace on the value.
205       uint32_t implementer;
206       HexStringToUInt(implementer_string->second, &implementer);
207       if (!CheckedNumeric<uint32_t>(implementer)
208                .AssignIfValid(&info.implementer)) {
209         info.implementer = 0;
210       }
211     }
212
213     auto part_number_string = FindFirstProcCpuKey(pairs, "CPU part");
214     if (part_number_string != pairs.end())
215       HexStringToUInt(part_number_string->second, &info.part_number);
216
217     return info;
218   }());
219
220   return *info;
221 }
222 #endif  // defined(ARCH_CPU_ARM_FAMILY) && (BUILDFLAG(IS_ANDROID) ||
223         // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
224
225 }  // namespace
226
227 void CPU::Initialize(bool require_branding) {
228 #if defined(ARCH_CPU_X86_FAMILY)
229   int cpu_info[4] = {-1};
230   // This array is used to temporarily hold the vendor name and then the brand
231   // name. Thus it has to be big enough for both use cases. There are
232   // static_asserts below for each of the use cases to make sure this array is
233   // big enough.
234   char cpu_string[sizeof(cpu_info) * 3 + 1];
235
236   // __cpuid with an InfoType argument of 0 returns the number of
237   // valid Ids in CPUInfo[0] and the CPU identification string in
238   // the other three array elements. The CPU identification string is
239   // not in linear order. The code below arranges the information
240   // in a human readable form. The human readable order is CPUInfo[1] |
241   // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped
242   // before using memcpy() to copy these three array elements to |cpu_string|.
243   __cpuid(cpu_info, 0);
244   int num_ids = cpu_info[0];
245   std::swap(cpu_info[2], cpu_info[3]);
246   static constexpr size_t kVendorNameSize = 3 * sizeof(cpu_info[1]);
247   static_assert(kVendorNameSize < std::size(cpu_string),
248                 "cpu_string too small");
249   memcpy(cpu_string, &cpu_info[1], kVendorNameSize);
250   cpu_string[kVendorNameSize] = '\0';
251   cpu_vendor_ = cpu_string;
252
253   // Interpret CPU feature information.
254   if (num_ids > 0) {
255     int cpu_info7[4] = {0};
256     __cpuid(cpu_info, 1);
257     if (num_ids >= 7) {
258       __cpuid(cpu_info7, 7);
259     }
260     signature_ = cpu_info[0];
261     stepping_ = cpu_info[0] & 0xf;
262     type_ = (cpu_info[0] >> 12) & 0x3;
263     internal::X86ModelInfo results =
264         internal::ComputeX86FamilyAndModel(cpu_vendor_, signature_);
265     family_ = results.family;
266     model_ = results.model;
267     ext_family_ = results.ext_family;
268     ext_model_ = results.ext_model;
269     has_mmx_ =   (cpu_info[3] & 0x00800000) != 0;
270     has_sse_ =   (cpu_info[3] & 0x02000000) != 0;
271     has_sse2_ =  (cpu_info[3] & 0x04000000) != 0;
272     has_sse3_ =  (cpu_info[2] & 0x00000001) != 0;
273     has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
274     has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
275     has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
276     has_popcnt_ = (cpu_info[2] & 0x00800000) != 0;
277
278     // "Hypervisor Present Bit: Bit 31 of ECX of CPUID leaf 0x1."
279     // See https://lwn.net/Articles/301888/
280     // This is checking for any hypervisor. Hypervisors may choose not to
281     // announce themselves. Hypervisors trap CPUID and sometimes return
282     // different results to underlying hardware.
283     is_running_in_vm_ = (static_cast<uint32_t>(cpu_info[2]) & 0x80000000) != 0;
284
285     // AVX instructions will generate an illegal instruction exception unless
286     //   a) they are supported by the CPU,
287     //   b) XSAVE is supported by the CPU and
288     //   c) XSAVE is enabled by the kernel.
289     // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
290     //
291     // In addition, we have observed some crashes with the xgetbv instruction
292     // even after following Intel's example code. (See crbug.com/375968.)
293     // Because of that, we also test the XSAVE bit because its description in
294     // the CPUID documentation suggests that it signals xgetbv support.
295     has_avx_ =
296         (cpu_info[2] & 0x10000000) != 0 &&
297         (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
298         (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
299         (xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
300     has_aesni_ = (cpu_info[2] & 0x02000000) != 0;
301     has_fma3_ = (cpu_info[2] & 0x00001000) != 0;
302     has_avx2_ = has_avx_ && (cpu_info7[1] & 0x00000020) != 0;
303
304     has_pku_ = (cpu_info7[2] & 0x00000008) != 0;
305   }
306
307   // Get the brand string of the cpu.
308   __cpuid(cpu_info, static_cast<int>(0x80000000));
309   const uint32_t max_parameter = static_cast<uint32_t>(cpu_info[0]);
310
311   static constexpr uint32_t kParameterStart = 0x80000002;
312   static constexpr uint32_t kParameterEnd = 0x80000004;
313   static constexpr uint32_t kParameterSize =
314       kParameterEnd - kParameterStart + 1;
315   static_assert(kParameterSize * sizeof(cpu_info) + 1 == std::size(cpu_string),
316                 "cpu_string has wrong size");
317
318   if (max_parameter >= kParameterEnd) {
319     size_t i = 0;
320     for (uint32_t parameter = kParameterStart; parameter <= kParameterEnd;
321          ++parameter) {
322       __cpuid(cpu_info, static_cast<int>(parameter));
323       memcpy(&cpu_string[i], cpu_info, sizeof(cpu_info));
324       i += sizeof(cpu_info);
325     }
326     cpu_string[i] = '\0';
327     cpu_brand_ = cpu_string;
328   }
329
330   static constexpr uint32_t kParameterContainingNonStopTimeStampCounter =
331       0x80000007;
332   if (max_parameter >= kParameterContainingNonStopTimeStampCounter) {
333     __cpuid(cpu_info,
334             static_cast<int>(kParameterContainingNonStopTimeStampCounter));
335     has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
336   }
337
338   if (!has_non_stop_time_stamp_counter_ && is_running_in_vm_) {
339     int cpu_info_hv[4] = {};
340     __cpuid(cpu_info_hv, 0x40000000);
341     if (cpu_info_hv[1] == 0x7263694D &&  // Micr
342         cpu_info_hv[2] == 0x666F736F &&  // osof
343         cpu_info_hv[3] == 0x76482074) {  // t Hv
344       // If CPUID says we have a variant TSC and a hypervisor has identified
345       // itself and the hypervisor says it is Microsoft Hyper-V, then treat
346       // TSC as invariant.
347       //
348       // Microsoft Hyper-V hypervisor reports variant TSC as there are some
349       // scenarios (eg. VM live migration) where the TSC is variant, but for
350       // our purposes we can treat it as invariant.
351       has_non_stop_time_stamp_counter_ = true;
352     }
353   }
354 #elif defined(ARCH_CPU_ARM_FAMILY)
355 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
356   if (require_branding) {
357     const ProcCpuInfo& info = ParseProcCpu();
358     cpu_brand_ = info.brand;
359     implementer_ = info.implementer;
360     part_number_ = info.part_number;
361   }
362
363 #if defined(ARCH_CPU_ARM64)
364   // Check for Armv8.5-A BTI/MTE support, exposed via HWCAP2
365   unsigned long hwcap2 = getauxval(AT_HWCAP2);
366   has_mte_ = hwcap2 & HWCAP2_MTE;
367   has_bti_ = hwcap2 & HWCAP2_BTI;
368 #endif
369
370 #elif BUILDFLAG(IS_WIN)
371   // Windows makes high-resolution thread timing information available in
372   // user-space.
373   has_non_stop_time_stamp_counter_ = true;
374 #endif
375 #endif
376 }
377
378 #if defined(ARCH_CPU_X86_FAMILY)
379 CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const {
380   if (has_avx2()) return AVX2;
381   if (has_fma3()) return FMA3;
382   if (has_avx()) return AVX;
383   if (has_sse42()) return SSE42;
384   if (has_sse41()) return SSE41;
385   if (has_ssse3()) return SSSE3;
386   if (has_sse3()) return SSE3;
387   if (has_sse2()) return SSE2;
388   if (has_sse()) return SSE;
389   return PENTIUM;
390 }
391 #endif
392
393 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
394     BUILDFLAG(IS_AIX)
395 namespace {
396
397 constexpr char kTimeInStatePath[] =
398     "/sys/devices/system/cpu/cpu%" PRIuS "/cpufreq/stats/time_in_state";
399 constexpr char kPhysicalPackageIdPath[] =
400     "/sys/devices/system/cpu/cpu%" PRIuS "/topology/physical_package_id";
401 constexpr char kCoreIdleStateTimePath[] =
402     "/sys/devices/system/cpu/cpu%" PRIuS "/cpuidle/state%d/time";
403
404 bool SupportsTimeInState() {
405   // Reading from time_in_state doesn't block (it amounts to reading a struct
406   // from the cpufreq-stats kernel driver).
407   ThreadRestrictions::ScopedAllowIO allow_io;
408   // Check if the time_in_state path for the first core is readable.
409   FilePath time_in_state_path(
410       StringPrintf(kTimeInStatePath, /*core_index=*/size_t{0}));
411   ScopedFILE file_stream(OpenFile(time_in_state_path, "rb"));
412   return static_cast<bool>(file_stream);
413 }
414
415 bool ParseTimeInState(const std::string& content,
416                       CPU::CoreType core_type,
417                       size_t core_index,
418                       CPU::TimeInState& time_in_state) {
419   const char* begin = content.data();
420   size_t max_pos = content.size() - 1;
421
422   // Example time_in_state content:
423   // ---
424   // 300000 1
425   // 403200 0
426   // 499200 15
427   // ---
428
429   // Iterate over the individual lines.
430   for (size_t pos = 0; pos <= max_pos;) {
431     int num_chars = 0;
432
433     // Each line should have two integer fields, frequency (kHz) and time (in
434     // jiffies), separated by a space, e.g. "2419200 132".
435     uint64_t frequency;
436     int64_t time;
437     int matches = sscanf(begin + pos, "%" PRIu64 " %" PRId64 "\n%n", &frequency,
438                          &time, &num_chars);
439     if (matches != 2)
440       return false;
441
442     // Skip zero-valued entries in the output list (no time spent at this
443     // frequency).
444     if (time > 0) {
445       time_in_state.push_back({core_type, core_index, frequency,
446                                internal::ClockTicksToTimeDelta(time)});
447     }
448
449     // Advance line.
450     DCHECK_GT(num_chars, 0);
451     pos += static_cast<size_t>(num_chars);
452   }
453
454   return true;
455 }
456
457 bool SupportsCoreIdleTimes() {
458   // Reading from the cpuidle driver doesn't block.
459   ThreadRestrictions::ScopedAllowIO allow_io;
460   // Check if the path for the idle time in state 0 for core 0 is readable.
461   FilePath idle_state0_path(StringPrintf(
462       kCoreIdleStateTimePath, /*core_index=*/size_t{0}, /*idle_state=*/0));
463   ScopedFILE file_stream(OpenFile(idle_state0_path, "rb"));
464   return static_cast<bool>(file_stream);
465 }
466
467 std::vector<CPU::CoreType> GuessCoreTypes() {
468   // Try to guess the CPU architecture and cores of each cluster by comparing
469   // the maximum frequencies of the available (online and offline) cores.
470   const char kCPUMaxFreqPath[] =
471       "/sys/devices/system/cpu/cpu%" PRIuS "/cpufreq/cpuinfo_max_freq";
472   size_t num_cpus = static_cast<size_t>(SysInfo::NumberOfProcessors());
473   std::vector<CPU::CoreType> core_index_to_type(num_cpus,
474                                                 CPU::CoreType::kUnknown);
475
476   std::vector<uint32_t> max_core_frequencies_mhz(num_cpus, 0);
477   flat_set<uint32_t> frequencies_mhz;
478
479   {
480     // Reading from cpuinfo_max_freq doesn't block (it amounts to reading a
481     // struct field from the cpufreq kernel driver).
482     ThreadRestrictions::ScopedAllowIO allow_io;
483     for (size_t core_index = 0; core_index < num_cpus; ++core_index) {
484       std::string content;
485       uint32_t frequency_khz = 0;
486       auto path = StringPrintf(kCPUMaxFreqPath, core_index);
487       if (ReadFileToString(FilePath(path), &content))
488         StringToUint(content, &frequency_khz);
489       uint32_t frequency_mhz = frequency_khz / 1000;
490       max_core_frequencies_mhz[core_index] = frequency_mhz;
491       if (frequency_mhz > 0)
492         frequencies_mhz.insert(frequency_mhz);
493     }
494   }
495
496   size_t num_frequencies = frequencies_mhz.size();
497
498   for (size_t core_index = 0; core_index < num_cpus; ++core_index) {
499     uint32_t core_frequency_mhz = max_core_frequencies_mhz[core_index];
500
501     CPU::CoreType core_type = CPU::CoreType::kOther;
502     if (num_frequencies == 1u) {
503       core_type = CPU::CoreType::kSymmetric;
504     } else if (num_frequencies == 2u || num_frequencies == 3u) {
505       auto it = frequencies_mhz.find(core_frequency_mhz);
506       if (it != frequencies_mhz.end()) {
507         // flat_set is sorted.
508         ptrdiff_t frequency_index = it - frequencies_mhz.begin();
509         switch (frequency_index) {
510           case 0:
511             core_type = num_frequencies == 2u
512                             ? CPU::CoreType::kBigLittle_Little
513                             : CPU::CoreType::kBigLittleBigger_Little;
514             break;
515           case 1:
516             core_type = num_frequencies == 2u
517                             ? CPU::CoreType::kBigLittle_Big
518                             : CPU::CoreType::kBigLittleBigger_Big;
519             break;
520           case 2:
521             DCHECK_EQ(num_frequencies, 3u);
522             core_type = CPU::CoreType::kBigLittleBigger_Bigger;
523             break;
524           default:
525             NOTREACHED();
526             break;
527         }
528       }
529     }
530     core_index_to_type[core_index] = core_type;
531   }
532
533   return core_index_to_type;
534 }
535
536 }  // namespace
537
538 // static
539 const std::vector<CPU::CoreType>& CPU::GetGuessedCoreTypes() {
540   static NoDestructor<std::vector<CoreType>> kCoreTypes(GuessCoreTypes());
541   return *kCoreTypes.get();
542 }
543
544 // static
545 bool CPU::GetTimeInState(TimeInState& time_in_state) {
546   time_in_state.clear();
547
548   // The kernel may not support the cpufreq-stats driver.
549   static const bool kSupportsTimeInState = SupportsTimeInState();
550   if (!kSupportsTimeInState)
551     return false;
552
553   static const std::vector<CoreType>& kCoreTypes = GetGuessedCoreTypes();
554
555   // time_in_state is reported per cluster. Identify the first cores of each
556   // cluster.
557   static NoDestructor<std::vector<size_t>> kFirstCoresIndexes([]() {
558     std::vector<size_t> first_cores;
559     int last_core_package_id = 0;
560     for (size_t core_index = 0;
561          core_index < static_cast<size_t>(SysInfo::NumberOfProcessors());
562          core_index++) {
563       // Reading from physical_package_id doesn't block (it amounts to reading a
564       // struct field from the kernel).
565       ThreadRestrictions::ScopedAllowIO allow_io;
566
567       FilePath package_id_path(
568           StringPrintf(kPhysicalPackageIdPath, core_index));
569       std::string package_id_str;
570       if (!ReadFileToString(package_id_path, &package_id_str))
571         return std::vector<size_t>();
572       int package_id;
573       base::StringPiece trimmed = base::TrimWhitespaceASCII(
574           package_id_str, base::TrimPositions::TRIM_ALL);
575       if (!base::StringToInt(trimmed, &package_id))
576         return std::vector<size_t>();
577
578       if (last_core_package_id != package_id || core_index == 0)
579         first_cores.push_back(core_index);
580
581       last_core_package_id = package_id;
582     }
583     return first_cores;
584   }());
585
586   if (kFirstCoresIndexes->empty())
587     return false;
588
589   // Reading from time_in_state doesn't block (it amounts to reading a struct
590   // from the cpufreq-stats kernel driver).
591   ThreadRestrictions::ScopedAllowIO allow_io;
592
593   // Read the time_in_state for each cluster from the /sys directory of the
594   // cluster's first core.
595   for (size_t cluster_core_index : *kFirstCoresIndexes) {
596     FilePath time_in_state_path(
597         StringPrintf(kTimeInStatePath, cluster_core_index));
598
599     std::string buffer;
600     if (!ReadFileToString(time_in_state_path, &buffer))
601       return false;
602
603     if (!ParseTimeInState(buffer, kCoreTypes[cluster_core_index],
604                           cluster_core_index, time_in_state)) {
605       return false;
606     }
607   }
608
609   return true;
610 }
611
612 // static
613 bool CPU::GetCumulativeCoreIdleTimes(CoreIdleTimes& idle_times) {
614   idle_times.clear();
615
616   // The kernel may not support the cpufreq-stats driver.
617   static const bool kSupportsIdleTimes = SupportsCoreIdleTimes();
618   if (!kSupportsIdleTimes)
619     return false;
620
621   // Reading from the cpuidle driver doesn't block.
622   ThreadRestrictions::ScopedAllowIO allow_io;
623
624   size_t num_cpus = static_cast<size_t>(SysInfo::NumberOfProcessors());
625
626   bool success = false;
627   for (size_t core_index = 0; core_index < num_cpus; ++core_index) {
628     std::string content;
629     TimeDelta idle_time;
630
631     // The number of idle states is system/CPU dependent, so we increment and
632     // try to read each state until we fail.
633     for (int state_index = 0;; ++state_index) {
634       auto path = StringPrintf(kCoreIdleStateTimePath, core_index, state_index);
635       uint64_t idle_state_time = 0;
636       if (!ReadFileToString(FilePath(path), &content))
637         break;
638       StringToUint64(content, &idle_state_time);
639       idle_time += Microseconds(idle_state_time);
640     }
641
642     idle_times.push_back(idle_time);
643
644     // At least one of the cores should have some idle time, otherwise we report
645     // a failure.
646     success |= idle_time.is_positive();
647   }
648
649   return success;
650 }
651 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
652         // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX)
653
654 const CPU& CPU::GetInstanceNoAllocation() {
655   static const base::NoDestructor<const CPU> cpu(CPU(false));
656
657   return *cpu;
658 }
659
660 }  // namespace base