xref: /aosp_15_r20/external/cronet/base/system/sys_info_posix.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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