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