1 // Copyright (c) 2011 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/sys_info.h"
6
7 #include <errno.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 #include <sys/param.h>
12 #include <sys/resource.h>
13 #include <sys/utsname.h>
14 #include <unistd.h>
15
16 #include "base/files/file_util.h"
17 #include "base/lazy_instance.h"
18 #include "base/logging.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/sys_info_internal.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "build/build_config.h"
23
24 #if defined(OS_ANDROID)
25 #include <sys/vfs.h>
26 #define statvfs statfs // Android uses a statvfs-like statfs struct and call.
27 #else
28 #include <sys/statvfs.h>
29 #endif
30
31 namespace {
32
33 #if !defined(OS_OPENBSD)
NumberOfProcessors()34 int NumberOfProcessors() {
35 // sysconf returns the number of "logical" (not "physical") processors on both
36 // Mac and Linux. So we get the number of max available "logical" processors.
37 //
38 // Note that the number of "currently online" processors may be fewer than the
39 // returned value of NumberOfProcessors(). On some platforms, the kernel may
40 // make some processors offline intermittently, to save power when system
41 // loading is low.
42 //
43 // One common use case that needs to know the processor count is to create
44 // optimal number of threads for optimization. It should make plan according
45 // to the number of "max available" processors instead of "currently online"
46 // ones. The kernel should be smart enough to make all processors online when
47 // it has sufficient number of threads waiting to run.
48 long res = sysconf(_SC_NPROCESSORS_CONF);
49 if (res == -1) {
50 NOTREACHED();
51 return 1;
52 }
53
54 return static_cast<int>(res);
55 }
56
57 base::LazyInstance<
58 base::internal::LazySysInfoValue<int, NumberOfProcessors> >::Leaky
59 g_lazy_number_of_processors = LAZY_INSTANCE_INITIALIZER;
60 #endif
61
AmountOfVirtualMemory()62 int64_t AmountOfVirtualMemory() {
63 struct rlimit limit;
64 int result = getrlimit(RLIMIT_DATA, &limit);
65 if (result != 0) {
66 NOTREACHED();
67 return 0;
68 }
69 return limit.rlim_cur == RLIM_INFINITY ? 0 : limit.rlim_cur;
70 }
71
72 base::LazyInstance<
73 base::internal::LazySysInfoValue<int64_t, AmountOfVirtualMemory>>::Leaky
74 g_lazy_virtual_memory = LAZY_INSTANCE_INITIALIZER;
75
GetDiskSpaceInfo(const base::FilePath & path,int64_t * available_bytes,int64_t * total_bytes)76 bool GetDiskSpaceInfo(const base::FilePath& path,
77 int64_t* available_bytes,
78 int64_t* total_bytes) {
79 struct statvfs stats;
80 if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
81 return false;
82
83 if (available_bytes)
84 *available_bytes = static_cast<int64_t>(stats.f_bavail) * stats.f_frsize;
85 if (total_bytes)
86 *total_bytes = static_cast<int64_t>(stats.f_blocks) * stats.f_frsize;
87 return true;
88 }
89
90 } // namespace
91
92 namespace base {
93
94 #if !defined(OS_OPENBSD)
NumberOfProcessors()95 int SysInfo::NumberOfProcessors() {
96 return g_lazy_number_of_processors.Get().value();
97 }
98 #endif
99
100 // static
AmountOfVirtualMemory()101 int64_t SysInfo::AmountOfVirtualMemory() {
102 return g_lazy_virtual_memory.Get().value();
103 }
104
105 // static
AmountOfFreeDiskSpace(const FilePath & path)106 int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
107 base::ThreadRestrictions::AssertIOAllowed();
108
109 int64_t available;
110 if (!GetDiskSpaceInfo(path, &available, nullptr))
111 return -1;
112 return available;
113 }
114
115 // static
AmountOfTotalDiskSpace(const FilePath & path)116 int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
117 base::ThreadRestrictions::AssertIOAllowed();
118
119 int64_t total;
120 if (!GetDiskSpaceInfo(path, nullptr, &total))
121 return -1;
122 return total;
123 }
124
125 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
126 // static
OperatingSystemName()127 std::string SysInfo::OperatingSystemName() {
128 struct utsname info;
129 if (uname(&info) < 0) {
130 NOTREACHED();
131 return std::string();
132 }
133 return std::string(info.sysname);
134 }
135 #endif
136
137 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
138 // static
OperatingSystemVersion()139 std::string SysInfo::OperatingSystemVersion() {
140 struct utsname info;
141 if (uname(&info) < 0) {
142 NOTREACHED();
143 return std::string();
144 }
145 return std::string(info.release);
146 }
147 #endif
148
149 // static
OperatingSystemArchitecture()150 std::string SysInfo::OperatingSystemArchitecture() {
151 struct utsname info;
152 if (uname(&info) < 0) {
153 NOTREACHED();
154 return std::string();
155 }
156 std::string arch(info.machine);
157 if (arch == "i386" || arch == "i486" || arch == "i586" || arch == "i686") {
158 arch = "x86";
159 } else if (arch == "amd64") {
160 arch = "x86_64";
161 }
162 return arch;
163 }
164
165 // static
VMAllocationGranularity()166 size_t SysInfo::VMAllocationGranularity() {
167 return getpagesize();
168 }
169
170 } // namespace base
171