xref: /aosp_15_r20/external/libchrome/base/sys_info_posix.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/sys_info.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <errno.h>
8*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
9*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
10*635a8641SAndroid Build Coastguard Worker #include <string.h>
11*635a8641SAndroid Build Coastguard Worker #include <sys/param.h>
12*635a8641SAndroid Build Coastguard Worker #include <sys/utsname.h>
13*635a8641SAndroid Build Coastguard Worker #include <unistd.h>
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker #include "base/files/file_util.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/sys_info_internal.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
21*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker #if !defined(OS_FUCHSIA)
24*635a8641SAndroid Build Coastguard Worker #include <sys/resource.h>
25*635a8641SAndroid Build Coastguard Worker #endif
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
28*635a8641SAndroid Build Coastguard Worker #include <sys/vfs.h>
29*635a8641SAndroid Build Coastguard Worker #define statvfs statfs  // Android uses a statvfs-like statfs struct and call.
30*635a8641SAndroid Build Coastguard Worker #else
31*635a8641SAndroid Build Coastguard Worker #include <sys/statvfs.h>
32*635a8641SAndroid Build Coastguard Worker #endif
33*635a8641SAndroid Build Coastguard Worker 
34*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX)
35*635a8641SAndroid Build Coastguard Worker #include <linux/magic.h>
36*635a8641SAndroid Build Coastguard Worker #include <sys/vfs.h>
37*635a8641SAndroid Build Coastguard Worker #endif
38*635a8641SAndroid Build Coastguard Worker 
39*635a8641SAndroid Build Coastguard Worker namespace {
40*635a8641SAndroid Build Coastguard Worker 
41*635a8641SAndroid Build Coastguard Worker #if !defined(OS_OPENBSD) && !defined(OS_FUCHSIA)
NumberOfProcessors()42*635a8641SAndroid Build Coastguard Worker int NumberOfProcessors() {
43*635a8641SAndroid Build Coastguard Worker   // sysconf returns the number of "logical" (not "physical") processors on both
44*635a8641SAndroid Build Coastguard Worker   // Mac and Linux.  So we get the number of max available "logical" processors.
45*635a8641SAndroid Build Coastguard Worker   //
46*635a8641SAndroid Build Coastguard Worker   // Note that the number of "currently online" processors may be fewer than the
47*635a8641SAndroid Build Coastguard Worker   // returned value of NumberOfProcessors(). On some platforms, the kernel may
48*635a8641SAndroid Build Coastguard Worker   // make some processors offline intermittently, to save power when system
49*635a8641SAndroid Build Coastguard Worker   // loading is low.
50*635a8641SAndroid Build Coastguard Worker   //
51*635a8641SAndroid Build Coastguard Worker   // One common use case that needs to know the processor count is to create
52*635a8641SAndroid Build Coastguard Worker   // optimal number of threads for optimization. It should make plan according
53*635a8641SAndroid Build Coastguard Worker   // to the number of "max available" processors instead of "currently online"
54*635a8641SAndroid Build Coastguard Worker   // ones. The kernel should be smart enough to make all processors online when
55*635a8641SAndroid Build Coastguard Worker   // it has sufficient number of threads waiting to run.
56*635a8641SAndroid Build Coastguard Worker   long res = sysconf(_SC_NPROCESSORS_CONF);
57*635a8641SAndroid Build Coastguard Worker   if (res == -1) {
58*635a8641SAndroid Build Coastguard Worker     NOTREACHED();
59*635a8641SAndroid Build Coastguard Worker     return 1;
60*635a8641SAndroid Build Coastguard Worker   }
61*635a8641SAndroid Build Coastguard Worker 
62*635a8641SAndroid Build Coastguard Worker   return static_cast<int>(res);
63*635a8641SAndroid Build Coastguard Worker }
64*635a8641SAndroid Build Coastguard Worker 
65*635a8641SAndroid Build Coastguard Worker base::LazyInstance<
66*635a8641SAndroid Build Coastguard Worker     base::internal::LazySysInfoValue<int, NumberOfProcessors> >::Leaky
67*635a8641SAndroid Build Coastguard Worker     g_lazy_number_of_processors = LAZY_INSTANCE_INITIALIZER;
68*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_OPENBSD) && !defined(OS_FUCHSIA)
69*635a8641SAndroid Build Coastguard Worker 
70*635a8641SAndroid Build Coastguard Worker #if !defined(OS_FUCHSIA)
AmountOfVirtualMemory()71*635a8641SAndroid Build Coastguard Worker int64_t AmountOfVirtualMemory() {
72*635a8641SAndroid Build Coastguard Worker   struct rlimit limit;
73*635a8641SAndroid Build Coastguard Worker   int result = getrlimit(RLIMIT_DATA, &limit);
74*635a8641SAndroid Build Coastguard Worker   if (result != 0) {
75*635a8641SAndroid Build Coastguard Worker     NOTREACHED();
76*635a8641SAndroid Build Coastguard Worker     return 0;
77*635a8641SAndroid Build Coastguard Worker   }
78*635a8641SAndroid Build Coastguard Worker   return limit.rlim_cur == RLIM_INFINITY ? 0 : limit.rlim_cur;
79*635a8641SAndroid Build Coastguard Worker }
80*635a8641SAndroid Build Coastguard Worker 
81*635a8641SAndroid Build Coastguard Worker base::LazyInstance<
82*635a8641SAndroid Build Coastguard Worker     base::internal::LazySysInfoValue<int64_t, AmountOfVirtualMemory>>::Leaky
83*635a8641SAndroid Build Coastguard Worker     g_lazy_virtual_memory = LAZY_INSTANCE_INITIALIZER;
84*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_FUCHSIA)
85*635a8641SAndroid Build Coastguard Worker 
86*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX)
IsStatsZeroIfUnlimited(const base::FilePath & path)87*635a8641SAndroid Build Coastguard Worker bool IsStatsZeroIfUnlimited(const base::FilePath& path) {
88*635a8641SAndroid Build Coastguard Worker   struct statfs stats;
89*635a8641SAndroid Build Coastguard Worker 
90*635a8641SAndroid Build Coastguard Worker   if (HANDLE_EINTR(statfs(path.value().c_str(), &stats)) != 0)
91*635a8641SAndroid Build Coastguard Worker     return false;
92*635a8641SAndroid Build Coastguard Worker 
93*635a8641SAndroid Build Coastguard Worker   // In some platforms, |statfs_buf.f_type| is declared as signed, but some of
94*635a8641SAndroid Build Coastguard Worker   // the values will overflow it, causing narrowing warnings. Cast to the
95*635a8641SAndroid Build Coastguard Worker   // largest possible unsigned integer type to avoid it.
96*635a8641SAndroid Build Coastguard Worker   switch (static_cast<uintmax_t>(stats.f_type)) {
97*635a8641SAndroid Build Coastguard Worker     case TMPFS_MAGIC:
98*635a8641SAndroid Build Coastguard Worker     case HUGETLBFS_MAGIC:
99*635a8641SAndroid Build Coastguard Worker     case RAMFS_MAGIC:
100*635a8641SAndroid Build Coastguard Worker       return true;
101*635a8641SAndroid Build Coastguard Worker   }
102*635a8641SAndroid Build Coastguard Worker   return false;
103*635a8641SAndroid Build Coastguard Worker }
104*635a8641SAndroid Build Coastguard Worker #endif
105*635a8641SAndroid Build Coastguard Worker 
GetDiskSpaceInfo(const base::FilePath & path,int64_t * available_bytes,int64_t * total_bytes)106*635a8641SAndroid Build Coastguard Worker bool GetDiskSpaceInfo(const base::FilePath& path,
107*635a8641SAndroid Build Coastguard Worker                       int64_t* available_bytes,
108*635a8641SAndroid Build Coastguard Worker                       int64_t* total_bytes) {
109*635a8641SAndroid Build Coastguard Worker   struct statvfs stats;
110*635a8641SAndroid Build Coastguard Worker   if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
111*635a8641SAndroid Build Coastguard Worker     return false;
112*635a8641SAndroid Build Coastguard Worker 
113*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX)
114*635a8641SAndroid Build Coastguard Worker   const bool zero_size_means_unlimited =
115*635a8641SAndroid Build Coastguard Worker       stats.f_blocks == 0 && IsStatsZeroIfUnlimited(path);
116*635a8641SAndroid Build Coastguard Worker #else
117*635a8641SAndroid Build Coastguard Worker   const bool zero_size_means_unlimited = false;
118*635a8641SAndroid Build Coastguard Worker #endif
119*635a8641SAndroid Build Coastguard Worker 
120*635a8641SAndroid Build Coastguard Worker   if (available_bytes) {
121*635a8641SAndroid Build Coastguard Worker     *available_bytes =
122*635a8641SAndroid Build Coastguard Worker         zero_size_means_unlimited
123*635a8641SAndroid Build Coastguard Worker             ? std::numeric_limits<int64_t>::max()
124*635a8641SAndroid Build Coastguard Worker             : static_cast<int64_t>(stats.f_bavail) * stats.f_frsize;
125*635a8641SAndroid Build Coastguard Worker   }
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker   if (total_bytes) {
128*635a8641SAndroid Build Coastguard Worker     *total_bytes = zero_size_means_unlimited
129*635a8641SAndroid Build Coastguard Worker                        ? std::numeric_limits<int64_t>::max()
130*635a8641SAndroid Build Coastguard Worker                        : static_cast<int64_t>(stats.f_blocks) * stats.f_frsize;
131*635a8641SAndroid Build Coastguard Worker   }
132*635a8641SAndroid Build Coastguard Worker   return true;
133*635a8641SAndroid Build Coastguard Worker }
134*635a8641SAndroid Build Coastguard Worker 
135*635a8641SAndroid Build Coastguard Worker }  // namespace
136*635a8641SAndroid Build Coastguard Worker 
137*635a8641SAndroid Build Coastguard Worker namespace base {
138*635a8641SAndroid Build Coastguard Worker 
139*635a8641SAndroid Build Coastguard Worker #if !defined(OS_OPENBSD) && !defined(OS_FUCHSIA)
NumberOfProcessors()140*635a8641SAndroid Build Coastguard Worker int SysInfo::NumberOfProcessors() {
141*635a8641SAndroid Build Coastguard Worker   return g_lazy_number_of_processors.Get().value();
142*635a8641SAndroid Build Coastguard Worker }
143*635a8641SAndroid Build Coastguard Worker #endif
144*635a8641SAndroid Build Coastguard Worker 
145*635a8641SAndroid Build Coastguard Worker #if !defined(OS_FUCHSIA)
146*635a8641SAndroid Build Coastguard Worker // static
AmountOfVirtualMemory()147*635a8641SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfVirtualMemory() {
148*635a8641SAndroid Build Coastguard Worker   return g_lazy_virtual_memory.Get().value();
149*635a8641SAndroid Build Coastguard Worker }
150*635a8641SAndroid Build Coastguard Worker #endif
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker // static
AmountOfFreeDiskSpace(const FilePath & path)153*635a8641SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
154*635a8641SAndroid Build Coastguard Worker   AssertBlockingAllowed();
155*635a8641SAndroid Build Coastguard Worker 
156*635a8641SAndroid Build Coastguard Worker   int64_t available;
157*635a8641SAndroid Build Coastguard Worker   if (!GetDiskSpaceInfo(path, &available, nullptr))
158*635a8641SAndroid Build Coastguard Worker     return -1;
159*635a8641SAndroid Build Coastguard Worker   return available;
160*635a8641SAndroid Build Coastguard Worker }
161*635a8641SAndroid Build Coastguard Worker 
162*635a8641SAndroid Build Coastguard Worker // static
AmountOfTotalDiskSpace(const FilePath & path)163*635a8641SAndroid Build Coastguard Worker int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
164*635a8641SAndroid Build Coastguard Worker   AssertBlockingAllowed();
165*635a8641SAndroid Build Coastguard Worker 
166*635a8641SAndroid Build Coastguard Worker   int64_t total;
167*635a8641SAndroid Build Coastguard Worker   if (!GetDiskSpaceInfo(path, nullptr, &total))
168*635a8641SAndroid Build Coastguard Worker     return -1;
169*635a8641SAndroid Build Coastguard Worker   return total;
170*635a8641SAndroid Build Coastguard Worker }
171*635a8641SAndroid Build Coastguard Worker 
172*635a8641SAndroid Build Coastguard Worker #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
173*635a8641SAndroid Build Coastguard Worker // static
OperatingSystemName()174*635a8641SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemName() {
175*635a8641SAndroid Build Coastguard Worker   struct utsname info;
176*635a8641SAndroid Build Coastguard Worker   if (uname(&info) < 0) {
177*635a8641SAndroid Build Coastguard Worker     NOTREACHED();
178*635a8641SAndroid Build Coastguard Worker     return std::string();
179*635a8641SAndroid Build Coastguard Worker   }
180*635a8641SAndroid Build Coastguard Worker   return std::string(info.sysname);
181*635a8641SAndroid Build Coastguard Worker }
182*635a8641SAndroid Build Coastguard Worker #endif
183*635a8641SAndroid Build Coastguard Worker 
184*635a8641SAndroid Build Coastguard Worker #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
185*635a8641SAndroid Build Coastguard Worker // static
OperatingSystemVersion()186*635a8641SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemVersion() {
187*635a8641SAndroid Build Coastguard Worker   struct utsname info;
188*635a8641SAndroid Build Coastguard Worker   if (uname(&info) < 0) {
189*635a8641SAndroid Build Coastguard Worker     NOTREACHED();
190*635a8641SAndroid Build Coastguard Worker     return std::string();
191*635a8641SAndroid Build Coastguard Worker   }
192*635a8641SAndroid Build Coastguard Worker   return std::string(info.release);
193*635a8641SAndroid Build Coastguard Worker }
194*635a8641SAndroid Build Coastguard Worker #endif
195*635a8641SAndroid Build Coastguard Worker 
196*635a8641SAndroid Build Coastguard Worker #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
197*635a8641SAndroid Build Coastguard Worker // static
OperatingSystemVersionNumbers(int32_t * major_version,int32_t * minor_version,int32_t * bugfix_version)198*635a8641SAndroid Build Coastguard Worker void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
199*635a8641SAndroid Build Coastguard Worker                                             int32_t* minor_version,
200*635a8641SAndroid Build Coastguard Worker                                             int32_t* bugfix_version) {
201*635a8641SAndroid Build Coastguard Worker   struct utsname info;
202*635a8641SAndroid Build Coastguard Worker   if (uname(&info) < 0) {
203*635a8641SAndroid Build Coastguard Worker     NOTREACHED();
204*635a8641SAndroid Build Coastguard Worker     *major_version = 0;
205*635a8641SAndroid Build Coastguard Worker     *minor_version = 0;
206*635a8641SAndroid Build Coastguard Worker     *bugfix_version = 0;
207*635a8641SAndroid Build Coastguard Worker     return;
208*635a8641SAndroid Build Coastguard Worker   }
209*635a8641SAndroid Build Coastguard Worker   int num_read = sscanf(info.release, "%d.%d.%d", major_version, minor_version,
210*635a8641SAndroid Build Coastguard Worker                         bugfix_version);
211*635a8641SAndroid Build Coastguard Worker   if (num_read < 1)
212*635a8641SAndroid Build Coastguard Worker     *major_version = 0;
213*635a8641SAndroid Build Coastguard Worker   if (num_read < 2)
214*635a8641SAndroid Build Coastguard Worker     *minor_version = 0;
215*635a8641SAndroid Build Coastguard Worker   if (num_read < 3)
216*635a8641SAndroid Build Coastguard Worker     *bugfix_version = 0;
217*635a8641SAndroid Build Coastguard Worker }
218*635a8641SAndroid Build Coastguard Worker #endif
219*635a8641SAndroid Build Coastguard Worker 
220*635a8641SAndroid Build Coastguard Worker // static
OperatingSystemArchitecture()221*635a8641SAndroid Build Coastguard Worker std::string SysInfo::OperatingSystemArchitecture() {
222*635a8641SAndroid Build Coastguard Worker   struct utsname info;
223*635a8641SAndroid Build Coastguard Worker   if (uname(&info) < 0) {
224*635a8641SAndroid Build Coastguard Worker     NOTREACHED();
225*635a8641SAndroid Build Coastguard Worker     return std::string();
226*635a8641SAndroid Build Coastguard Worker   }
227*635a8641SAndroid Build Coastguard Worker   std::string arch(info.machine);
228*635a8641SAndroid Build Coastguard Worker   if (arch == "i386" || arch == "i486" || arch == "i586" || arch == "i686") {
229*635a8641SAndroid Build Coastguard Worker     arch = "x86";
230*635a8641SAndroid Build Coastguard Worker   } else if (arch == "amd64") {
231*635a8641SAndroid Build Coastguard Worker     arch = "x86_64";
232*635a8641SAndroid Build Coastguard Worker   } else if (std::string(info.sysname) == "AIX") {
233*635a8641SAndroid Build Coastguard Worker     arch = "ppc64";
234*635a8641SAndroid Build Coastguard Worker   }
235*635a8641SAndroid Build Coastguard Worker   return arch;
236*635a8641SAndroid Build Coastguard Worker }
237*635a8641SAndroid Build Coastguard Worker 
238*635a8641SAndroid Build Coastguard Worker // static
VMAllocationGranularity()239*635a8641SAndroid Build Coastguard Worker size_t SysInfo::VMAllocationGranularity() {
240*635a8641SAndroid Build Coastguard Worker   return getpagesize();
241*635a8641SAndroid Build Coastguard Worker }
242*635a8641SAndroid Build Coastguard Worker 
243*635a8641SAndroid Build Coastguard Worker }  // namespace base
244