1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/system/sys_info.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <errno.h>
8*6777b538SAndroid Build Coastguard Worker #include <sched.h>
9*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
11*6777b538SAndroid Build Coastguard Worker #include <string.h>
12*6777b538SAndroid Build Coastguard Worker #include <sys/param.h>
13*6777b538SAndroid Build Coastguard Worker #include <sys/resource.h>
14*6777b538SAndroid Build Coastguard Worker #include <sys/utsname.h>
15*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include <algorithm>
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/notimplemented.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/system/sys_info_internal.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
30*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
33*6777b538SAndroid Build Coastguard Worker #include <sys/vfs.h>
34*6777b538SAndroid Build Coastguard Worker #define statvfs statfs // Android uses a statvfs-like statfs struct and call.
35*6777b538SAndroid Build Coastguard Worker #else
36*6777b538SAndroid Build Coastguard Worker #include <sys/statvfs.h>
37*6777b538SAndroid Build Coastguard Worker #endif
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
40*6777b538SAndroid Build Coastguard Worker #include <linux/magic.h>
41*6777b538SAndroid Build Coastguard Worker #include <sys/vfs.h>
42*6777b538SAndroid Build Coastguard Worker #endif
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
45*6777b538SAndroid Build Coastguard Worker #include <optional>
46*6777b538SAndroid Build Coastguard Worker #endif
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker namespace {
49*6777b538SAndroid Build Coastguard Worker
AmountOfVirtualMemory()50*6777b538SAndroid Build Coastguard Worker uint64_t AmountOfVirtualMemory() {
51*6777b538SAndroid Build Coastguard Worker struct rlimit limit;
52*6777b538SAndroid Build Coastguard Worker int result = getrlimit(RLIMIT_DATA, &limit);
53*6777b538SAndroid Build Coastguard Worker if (result != 0) {
54*6777b538SAndroid Build Coastguard Worker NOTREACHED();
55*6777b538SAndroid Build Coastguard Worker return 0;
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker return limit.rlim_cur == RLIM_INFINITY ? 0 : limit.rlim_cur;
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker base::LazyInstance<
61*6777b538SAndroid Build Coastguard Worker base::internal::LazySysInfoValue<uint64_t, AmountOfVirtualMemory>>::Leaky
62*6777b538SAndroid Build Coastguard Worker g_lazy_virtual_memory = LAZY_INSTANCE_INITIALIZER;
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
IsStatsZeroIfUnlimited(const base::FilePath & path)65*6777b538SAndroid Build Coastguard Worker bool IsStatsZeroIfUnlimited(const base::FilePath& path) {
66*6777b538SAndroid Build Coastguard Worker struct statfs stats;
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker if (HANDLE_EINTR(statfs(path.value().c_str(), &stats)) != 0)
69*6777b538SAndroid Build Coastguard Worker return false;
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker // This static_cast is here because various libcs disagree about the size
72*6777b538SAndroid Build Coastguard Worker // and signedness of statfs::f_type. In particular, glibc has it as either a
73*6777b538SAndroid Build Coastguard Worker // signed long or a signed int depending on platform, and other libcs
74*6777b538SAndroid Build Coastguard Worker // (following the statfs(2) man page) use unsigned int instead. To avoid
75*6777b538SAndroid Build Coastguard Worker // either an unsigned -> signed cast, or a narrowing cast, we always upcast
76*6777b538SAndroid Build Coastguard Worker // statfs::f_type to unsigned long. :(
77*6777b538SAndroid Build Coastguard Worker switch (static_cast<unsigned long>(stats.f_type)) {
78*6777b538SAndroid Build Coastguard Worker case TMPFS_MAGIC:
79*6777b538SAndroid Build Coastguard Worker case HUGETLBFS_MAGIC:
80*6777b538SAndroid Build Coastguard Worker case RAMFS_MAGIC:
81*6777b538SAndroid Build Coastguard Worker return true;
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker return false;
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
86*6777b538SAndroid Build Coastguard Worker
GetDiskSpaceInfo(const base::FilePath & path,int64_t * available_bytes,int64_t * total_bytes)87*6777b538SAndroid Build Coastguard Worker bool GetDiskSpaceInfo(const base::FilePath& path,
88*6777b538SAndroid Build Coastguard Worker int64_t* available_bytes,
89*6777b538SAndroid Build Coastguard Worker int64_t* total_bytes) {
90*6777b538SAndroid Build Coastguard Worker struct statvfs stats;
91*6777b538SAndroid Build Coastguard Worker if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
92*6777b538SAndroid Build Coastguard Worker return false;
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
95*6777b538SAndroid Build Coastguard Worker const bool zero_size_means_unlimited =
96*6777b538SAndroid Build Coastguard Worker stats.f_blocks == 0 && IsStatsZeroIfUnlimited(path);
97*6777b538SAndroid Build Coastguard Worker #else
98*6777b538SAndroid Build Coastguard Worker const bool zero_size_means_unlimited = false;
99*6777b538SAndroid Build Coastguard Worker #endif
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker if (available_bytes) {
102*6777b538SAndroid Build Coastguard Worker *available_bytes =
103*6777b538SAndroid Build Coastguard Worker zero_size_means_unlimited
104*6777b538SAndroid Build Coastguard Worker ? std::numeric_limits<int64_t>::max()
105*6777b538SAndroid Build Coastguard Worker : base::saturated_cast<int64_t>(stats.f_bavail * stats.f_frsize);
106*6777b538SAndroid Build Coastguard Worker }
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker if (total_bytes) {
109*6777b538SAndroid Build Coastguard Worker *total_bytes =
110*6777b538SAndroid Build Coastguard Worker zero_size_means_unlimited
111*6777b538SAndroid Build Coastguard Worker ? std::numeric_limits<int64_t>::max()
112*6777b538SAndroid Build Coastguard Worker : base::saturated_cast<int64_t>(stats.f_blocks * stats.f_frsize);
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker return true;
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker } // namespace
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Worker namespace base {
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_OPENBSD)
122*6777b538SAndroid Build Coastguard Worker // static
NumberOfProcessors()123*6777b538SAndroid Build Coastguard Worker int SysInfo::NumberOfProcessors() {
124*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
125*6777b538SAndroid Build Coastguard Worker std::optional<int> number_of_physical_cores =
126*6777b538SAndroid Build Coastguard Worker internal::NumberOfProcessorsWhenCpuSecurityMitigationEnabled();
127*6777b538SAndroid Build Coastguard Worker if (number_of_physical_cores.has_value()) {
128*6777b538SAndroid Build Coastguard Worker return number_of_physical_cores.value();
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_MAC)
131*6777b538SAndroid Build Coastguard Worker
132*6777b538SAndroid Build Coastguard Worker // This value is cached to avoid computing this value in the sandbox, which
133*6777b538SAndroid Build Coastguard Worker // doesn't work on some platforms. The Mac-specific code above is not
134*6777b538SAndroid Build Coastguard Worker // included because changing the value at runtime is the best way to unittest
135*6777b538SAndroid Build Coastguard Worker // its behavior.
136*6777b538SAndroid Build Coastguard Worker static int cached_num_cpus = []() {
137*6777b538SAndroid Build Coastguard Worker // sysconf returns the number of "logical" (not "physical") processors on
138*6777b538SAndroid Build Coastguard Worker // both Mac and Linux. So we get the number of max available "logical"
139*6777b538SAndroid Build Coastguard Worker // processors.
140*6777b538SAndroid Build Coastguard Worker //
141*6777b538SAndroid Build Coastguard Worker // Note that the number of "currently online" processors may be fewer than
142*6777b538SAndroid Build Coastguard Worker // the returned value of NumberOfProcessors(). On some platforms, the kernel
143*6777b538SAndroid Build Coastguard Worker // may make some processors offline intermittently, to save power when
144*6777b538SAndroid Build Coastguard Worker // system loading is low.
145*6777b538SAndroid Build Coastguard Worker //
146*6777b538SAndroid Build Coastguard Worker // One common use case that needs to know the processor count is to create
147*6777b538SAndroid Build Coastguard Worker // optimal number of threads for optimization. It should make plan according
148*6777b538SAndroid Build Coastguard Worker // to the number of "max available" processors instead of "currently online"
149*6777b538SAndroid Build Coastguard Worker // ones. The kernel should be smart enough to make all processors online
150*6777b538SAndroid Build Coastguard Worker // when it has sufficient number of threads waiting to run.
151*6777b538SAndroid Build Coastguard Worker long res = sysconf(_SC_NPROCESSORS_CONF);
152*6777b538SAndroid Build Coastguard Worker if (res == -1) {
153*6777b538SAndroid Build Coastguard Worker // `res` can be -1 if this function is invoked under the sandbox, which
154*6777b538SAndroid Build Coastguard Worker // should never happen.
155*6777b538SAndroid Build Coastguard Worker NOTREACHED();
156*6777b538SAndroid Build Coastguard Worker return 1;
157*6777b538SAndroid Build Coastguard Worker }
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Worker int num_cpus = static_cast<int>(res);
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX)
162*6777b538SAndroid Build Coastguard Worker // Restrict the CPU count based on the process's CPU affinity mask, if
163*6777b538SAndroid Build Coastguard Worker // available.
164*6777b538SAndroid Build Coastguard Worker cpu_set_t* cpu_set = CPU_ALLOC(num_cpus);
165*6777b538SAndroid Build Coastguard Worker size_t cpu_set_size = CPU_ALLOC_SIZE(num_cpus);
166*6777b538SAndroid Build Coastguard Worker int ret = sched_getaffinity(0, cpu_set_size, cpu_set);
167*6777b538SAndroid Build Coastguard Worker if (ret == 0) {
168*6777b538SAndroid Build Coastguard Worker num_cpus = CPU_COUNT_S(cpu_set_size, cpu_set);
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker CPU_FREE(cpu_set);
171*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_LINUX)
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker return num_cpus;
174*6777b538SAndroid Build Coastguard Worker }();
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker return cached_num_cpus;
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker #endif // !BUILDFLAG(IS_OPENBSD)
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker // static
AmountOfVirtualMemory()181*6777b538SAndroid Build Coastguard Worker uint64_t SysInfo::AmountOfVirtualMemory() {
182*6777b538SAndroid Build Coastguard Worker return g_lazy_virtual_memory.Get().value();
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker // static
AmountOfFreeDiskSpace(const FilePath & path)186*6777b538SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
187*6777b538SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
188*6777b538SAndroid Build Coastguard Worker base::BlockingType::MAY_BLOCK);
189*6777b538SAndroid Build Coastguard Worker
190*6777b538SAndroid Build Coastguard Worker int64_t available;
191*6777b538SAndroid Build Coastguard Worker if (!GetDiskSpaceInfo(path, &available, nullptr))
192*6777b538SAndroid Build Coastguard Worker return -1;
193*6777b538SAndroid Build Coastguard Worker return available;
194*6777b538SAndroid Build Coastguard Worker }
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker // static
AmountOfTotalDiskSpace(const FilePath & path)197*6777b538SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
198*6777b538SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
199*6777b538SAndroid Build Coastguard Worker base::BlockingType::MAY_BLOCK);
200*6777b538SAndroid Build Coastguard Worker
201*6777b538SAndroid Build Coastguard Worker int64_t total;
202*6777b538SAndroid Build Coastguard Worker if (!GetDiskSpaceInfo(path, nullptr, &total))
203*6777b538SAndroid Build Coastguard Worker return -1;
204*6777b538SAndroid Build Coastguard Worker return total;
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)
208*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemName()209*6777b538SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemName() {
210*6777b538SAndroid Build Coastguard Worker struct utsname info;
211*6777b538SAndroid Build Coastguard Worker if (uname(&info) < 0) {
212*6777b538SAndroid Build Coastguard Worker NOTREACHED();
213*6777b538SAndroid Build Coastguard Worker return std::string();
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker return std::string(info.sysname);
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker #endif //! BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)
218*6777b538SAndroid Build Coastguard Worker
219*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
220*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemVersion()221*6777b538SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemVersion() {
222*6777b538SAndroid Build Coastguard Worker struct utsname info;
223*6777b538SAndroid Build Coastguard Worker if (uname(&info) < 0) {
224*6777b538SAndroid Build Coastguard Worker NOTREACHED();
225*6777b538SAndroid Build Coastguard Worker return std::string();
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker return std::string(info.release);
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker #endif
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
232*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemVersionNumbers(int32_t * major_version,int32_t * minor_version,int32_t * bugfix_version)233*6777b538SAndroid Build Coastguard Worker void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
234*6777b538SAndroid Build Coastguard Worker int32_t* minor_version,
235*6777b538SAndroid Build Coastguard Worker int32_t* bugfix_version) {
236*6777b538SAndroid Build Coastguard Worker struct utsname info;
237*6777b538SAndroid Build Coastguard Worker if (uname(&info) < 0) {
238*6777b538SAndroid Build Coastguard Worker NOTREACHED();
239*6777b538SAndroid Build Coastguard Worker *major_version = 0;
240*6777b538SAndroid Build Coastguard Worker *minor_version = 0;
241*6777b538SAndroid Build Coastguard Worker *bugfix_version = 0;
242*6777b538SAndroid Build Coastguard Worker return;
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker int num_read = sscanf(info.release, "%d.%d.%d", major_version, minor_version,
245*6777b538SAndroid Build Coastguard Worker bugfix_version);
246*6777b538SAndroid Build Coastguard Worker if (num_read < 1)
247*6777b538SAndroid Build Coastguard Worker *major_version = 0;
248*6777b538SAndroid Build Coastguard Worker if (num_read < 2)
249*6777b538SAndroid Build Coastguard Worker *minor_version = 0;
250*6777b538SAndroid Build Coastguard Worker if (num_read < 3)
251*6777b538SAndroid Build Coastguard Worker *bugfix_version = 0;
252*6777b538SAndroid Build Coastguard Worker }
253*6777b538SAndroid Build Coastguard Worker #endif
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_IOS)
256*6777b538SAndroid Build Coastguard Worker // static
OperatingSystemArchitecture()257*6777b538SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemArchitecture() {
258*6777b538SAndroid Build Coastguard Worker struct utsname info;
259*6777b538SAndroid Build Coastguard Worker if (uname(&info) < 0) {
260*6777b538SAndroid Build Coastguard Worker NOTREACHED();
261*6777b538SAndroid Build Coastguard Worker return std::string();
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker std::string arch(info.machine);
264*6777b538SAndroid Build Coastguard Worker if (arch == "i386" || arch == "i486" || arch == "i586" || arch == "i686") {
265*6777b538SAndroid Build Coastguard Worker arch = "x86";
266*6777b538SAndroid Build Coastguard Worker } else if (arch == "amd64") {
267*6777b538SAndroid Build Coastguard Worker arch = "x86_64";
268*6777b538SAndroid Build Coastguard Worker } else if (std::string(info.sysname) == "AIX") {
269*6777b538SAndroid Build Coastguard Worker arch = "ppc64";
270*6777b538SAndroid Build Coastguard Worker }
271*6777b538SAndroid Build Coastguard Worker return arch;
272*6777b538SAndroid Build Coastguard Worker }
273*6777b538SAndroid Build Coastguard Worker #endif // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_IOS)
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker // static
VMAllocationGranularity()276*6777b538SAndroid Build Coastguard Worker size_t SysInfo::VMAllocationGranularity() {
277*6777b538SAndroid Build Coastguard Worker return checked_cast<size_t>(getpagesize());
278*6777b538SAndroid Build Coastguard Worker }
279*6777b538SAndroid Build Coastguard Worker
280*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_APPLE)
281*6777b538SAndroid Build Coastguard Worker // static
NumberOfEfficientProcessorsImpl()282*6777b538SAndroid Build Coastguard Worker int SysInfo::NumberOfEfficientProcessorsImpl() {
283*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
284*6777b538SAndroid Build Coastguard Worker // Try to guess the CPU architecture and cores of each cluster by comparing
285*6777b538SAndroid Build Coastguard Worker // the maximum frequencies of the available (online and offline) cores.
286*6777b538SAndroid Build Coastguard Worker int num_cpus = SysInfo::NumberOfProcessors();
287*6777b538SAndroid Build Coastguard Worker DCHECK_GE(num_cpus, 0);
288*6777b538SAndroid Build Coastguard Worker std::vector<uint32_t> max_core_frequencies_khz(static_cast<size_t>(num_cpus),
289*6777b538SAndroid Build Coastguard Worker 0);
290*6777b538SAndroid Build Coastguard Worker for (int core_index = 0; core_index < num_cpus; ++core_index) {
291*6777b538SAndroid Build Coastguard Worker std::string content;
292*6777b538SAndroid Build Coastguard Worker auto path = StringPrintf(
293*6777b538SAndroid Build Coastguard Worker "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", core_index);
294*6777b538SAndroid Build Coastguard Worker if (!ReadFileToStringNonBlocking(FilePath(path), &content))
295*6777b538SAndroid Build Coastguard Worker return 0;
296*6777b538SAndroid Build Coastguard Worker if (!StringToUint(
297*6777b538SAndroid Build Coastguard Worker content,
298*6777b538SAndroid Build Coastguard Worker &max_core_frequencies_khz[static_cast<size_t>(core_index)]))
299*6777b538SAndroid Build Coastguard Worker return 0;
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker auto [min_max_core_frequencies_khz_it, max_max_core_frequencies_khz_it] =
303*6777b538SAndroid Build Coastguard Worker std::minmax_element(max_core_frequencies_khz.begin(),
304*6777b538SAndroid Build Coastguard Worker max_core_frequencies_khz.end());
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker if (*min_max_core_frequencies_khz_it == *max_max_core_frequencies_khz_it)
307*6777b538SAndroid Build Coastguard Worker return 0;
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker return static_cast<int>(std::count(max_core_frequencies_khz.begin(),
310*6777b538SAndroid Build Coastguard Worker max_core_frequencies_khz.end(),
311*6777b538SAndroid Build Coastguard Worker *min_max_core_frequencies_khz_it));
312*6777b538SAndroid Build Coastguard Worker #else
313*6777b538SAndroid Build Coastguard Worker NOTIMPLEMENTED();
314*6777b538SAndroid Build Coastguard Worker return 0;
315*6777b538SAndroid Build Coastguard Worker #endif
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker #endif // !BUILDFLAG(IS_APPLE)
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker } // namespace base
320