Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: webrtc/base/systeminfo.cc

Issue 1286163003: Move SystemInfo to rtc_base_approved and delete unused code. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Address comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/systeminfo.h ('k') | webrtc/base/systeminfo_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2008 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2008 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/base/systeminfo.h" 11 #include "webrtc/base/systeminfo.h"
12 12
13 #if defined(WEBRTC_WIN) 13 #if defined(WEBRTC_WIN)
14 #include <winsock2.h> 14 #include <winsock2.h>
15 #include <windows.h>
15 #ifndef EXCLUDE_D3D9 16 #ifndef EXCLUDE_D3D9
16 #include <d3d9.h> 17 #include <d3d9.h>
17 #endif 18 #endif
18 #include <intrin.h> // for __cpuid() 19 #include <intrin.h> // for __cpuid()
19 #elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) 20 #elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
20 #include <ApplicationServices/ApplicationServices.h> 21 #include <ApplicationServices/ApplicationServices.h>
21 #include <CoreServices/CoreServices.h> 22 #include <CoreServices/CoreServices.h>
22 #elif defined(WEBRTC_LINUX) 23 #elif defined(WEBRTC_LINUX)
23 #include <unistd.h> 24 #include <unistd.h>
24 #endif 25 #endif
25 #if defined(WEBRTC_MAC) 26 #if defined(WEBRTC_MAC)
26 #include <sys/sysctl.h> 27 #include <sys/sysctl.h>
27 #endif 28 #endif
28 29
29 #if defined(WEBRTC_WIN)
30 #include "webrtc/base/scoped_ptr.h"
31 #include "webrtc/base/win32.h"
32 #elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
33 #include "webrtc/base/macconversion.h"
34 #elif defined(WEBRTC_LINUX)
35 #include "webrtc/base/linux.h"
36 #endif
37 #include "webrtc/base/common.h" 30 #include "webrtc/base/common.h"
38 #include "webrtc/base/logging.h" 31 #include "webrtc/base/logging.h"
39 #include "webrtc/base/stringutils.h" 32 #include "webrtc/base/stringutils.h"
40 33
41 namespace rtc { 34 namespace rtc {
42 35
43 // See Also: http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx 36 // See Also: http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx
44 #if defined(WEBRTC_WIN) 37 #if !defined(WEBRTC_WIN)
45 typedef BOOL (WINAPI *LPFN_GLPI)(
46 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
47 PDWORD);
48
49 static void GetProcessorInformation(int* physical_cpus, int* cache_size) {
50 // GetLogicalProcessorInformation() is available on Windows XP SP3 and beyond.
51 LPFN_GLPI glpi = reinterpret_cast<LPFN_GLPI>(GetProcAddress(
52 GetModuleHandle(L"kernel32"),
53 "GetLogicalProcessorInformation"));
54 if (NULL == glpi) {
55 return;
56 }
57 // Determine buffer size, allocate and get processor information.
58 // Size can change between calls (unlikely), so a loop is done.
59 DWORD return_length = 0;
60 scoped_ptr<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]> infos;
61 while (!glpi(infos.get(), &return_length)) {
62 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
63 infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[
64 return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)]);
65 } else {
66 return;
67 }
68 }
69 *physical_cpus = 0;
70 *cache_size = 0;
71 for (size_t i = 0;
72 i < return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
73 if (infos[i].Relationship == RelationProcessorCore) {
74 ++*physical_cpus;
75 } else if (infos[i].Relationship == RelationCache) {
76 int next_cache_size = static_cast<int>(infos[i].Cache.Size);
77 if (next_cache_size >= *cache_size) {
78 *cache_size = next_cache_size;
79 }
80 }
81 }
82 return;
83 }
84 #else
85 // TODO(fbarchard): Use gcc 4.4 provided cpuid intrinsic 38 // TODO(fbarchard): Use gcc 4.4 provided cpuid intrinsic
86 // 32 bit fpic requires ebx be preserved 39 // 32 bit fpic requires ebx be preserved
87 #if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__) 40 #if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
88 static inline void __cpuid(int cpu_info[4], int info_type) { 41 static inline void __cpuid(int cpu_info[4], int info_type) {
89 __asm__ volatile ( // NOLINT 42 __asm__ volatile ( // NOLINT
90 "mov %%ebx, %%edi\n" 43 "mov %%ebx, %%edi\n"
91 "cpuid\n" 44 "cpuid\n"
92 "xchg %%edi, %%ebx\n" 45 "xchg %%edi, %%ebx\n"
93 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) 46 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
94 : "a"(info_type) 47 : "a"(info_type)
95 ); // NOLINT 48 ); // NOLINT
96 } 49 }
97 #elif defined(__i386__) || defined(__x86_64__) 50 #elif defined(__i386__) || defined(__x86_64__)
98 static inline void __cpuid(int cpu_info[4], int info_type) { 51 static inline void __cpuid(int cpu_info[4], int info_type) {
99 __asm__ volatile ( // NOLINT 52 __asm__ volatile ( // NOLINT
100 "cpuid\n" 53 "cpuid\n"
101 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) 54 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
102 : "a"(info_type) 55 : "a"(info_type)
103 ); // NOLINT 56 ); // NOLINT
104 } 57 }
105 #endif 58 #endif
106 #endif // WEBRTC_WIN 59 #endif // WEBRTC_WIN
107 60
108 // Note(fbarchard): 61 static int DetectNumberOfCores() {
109 // Family and model are extended family and extended model. 8 bits each. 62 // We fall back on assuming a single core in case of errors.
110 SystemInfo::SystemInfo() 63 int number_of_cores = 1;
111 : physical_cpus_(1), logical_cpus_(1), cache_size_(0),
112 cpu_family_(0), cpu_model_(0), cpu_stepping_(0),
113 cpu_speed_(0), memory_(0) {
114 // Initialize the basic information.
115 #if defined(__arm__) || defined(_M_ARM)
116 cpu_arch_ = SI_ARCH_ARM;
117 #elif defined(__x86_64__) || defined(_M_X64)
118 cpu_arch_ = SI_ARCH_X64;
119 #elif defined(__i386__) || defined(_M_IX86)
120 cpu_arch_ = SI_ARCH_X86;
121 #else
122 cpu_arch_ = SI_ARCH_UNKNOWN;
123 #endif
124 64
125 #if defined(WEBRTC_WIN) 65 #if defined(WEBRTC_WIN)
126 SYSTEM_INFO si; 66 SYSTEM_INFO si;
127 GetSystemInfo(&si); 67 GetSystemInfo(&si);
128 logical_cpus_ = si.dwNumberOfProcessors; 68 number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
129 GetProcessorInformation(&physical_cpus_, &cache_size_); 69 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
130 if (physical_cpus_ <= 0) { 70 number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
131 physical_cpus_ = logical_cpus_; 71 #elif defined(WEBRTC_MAC)
72 int name[] = {CTL_HW, HW_AVAILCPU};
73 size_t size = sizeof(number_of_cores);
74 if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) {
75 LOG(LS_ERROR) << "Failed to get number of cores";
76 number_of_cores = 1;
132 } 77 }
133 cpu_family_ = si.wProcessorLevel; 78 #else
134 cpu_model_ = si.wProcessorRevision >> 8; 79 LOG(LS_ERROR) << "No function to get number of cores";
135 cpu_stepping_ = si.wProcessorRevision & 0xFF;
136 #elif defined(WEBRTC_MAC)
137 uint32_t sysctl_value;
138 size_t length = sizeof(sysctl_value);
139 if (!sysctlbyname("hw.physicalcpu_max", &sysctl_value, &length, NULL, 0)) {
140 physical_cpus_ = static_cast<int>(sysctl_value);
141 }
142 length = sizeof(sysctl_value);
143 if (!sysctlbyname("hw.logicalcpu_max", &sysctl_value, &length, NULL, 0)) {
144 logical_cpus_ = static_cast<int>(sysctl_value);
145 }
146 uint64_t sysctl_value64;
147 length = sizeof(sysctl_value64);
148 if (!sysctlbyname("hw.l3cachesize", &sysctl_value64, &length, NULL, 0)) {
149 cache_size_ = static_cast<int>(sysctl_value64);
150 }
151 if (!cache_size_) {
152 length = sizeof(sysctl_value64);
153 if (!sysctlbyname("hw.l2cachesize", &sysctl_value64, &length, NULL, 0)) {
154 cache_size_ = static_cast<int>(sysctl_value64);
155 }
156 }
157 length = sizeof(sysctl_value);
158 if (!sysctlbyname("machdep.cpu.family", &sysctl_value, &length, NULL, 0)) {
159 cpu_family_ = static_cast<int>(sysctl_value);
160 }
161 length = sizeof(sysctl_value);
162 if (!sysctlbyname("machdep.cpu.model", &sysctl_value, &length, NULL, 0)) {
163 cpu_model_ = static_cast<int>(sysctl_value);
164 }
165 length = sizeof(sysctl_value);
166 if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) {
167 cpu_stepping_ = static_cast<int>(sysctl_value);
168 }
169 #elif defined(__native_client__)
170 // TODO(ryanpetrie): Implement this via PPAPI when it's available.
171 #else // WEBRTC_LINUX
172 ProcCpuInfo proc_info;
173 if (proc_info.LoadFromSystem()) {
174 proc_info.GetNumCpus(&logical_cpus_);
175 proc_info.GetNumPhysicalCpus(&physical_cpus_);
176 proc_info.GetCpuFamily(&cpu_family_);
177 #if defined(CPU_X86)
178 // These values only apply to x86 systems.
179 proc_info.GetSectionIntValue(0, "model", &cpu_model_);
180 proc_info.GetSectionIntValue(0, "stepping", &cpu_stepping_);
181 proc_info.GetSectionIntValue(0, "cpu MHz", &cpu_speed_);
182 proc_info.GetSectionIntValue(0, "cache size", &cache_size_);
183 cache_size_ *= 1024;
184 #endif 80 #endif
185 } 81
186 // ProcCpuInfo reads cpu speed from "cpu MHz" under /proc/cpuinfo. 82 LOG(LS_INFO) << "Available number of cores: " << number_of_cores;
187 // But that number is a moving target which can change on-the-fly according to 83
188 // many factors including system workload. 84 return number_of_cores;
189 // See /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors. 85 }
190 // The one in /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq is more 86
191 // accurate. We use it as our cpu speed when it is available. 87 // Statically cache the number of system cores available since if the process
192 // cpuinfo_max_freq is measured in KHz and requires conversion to MHz. 88 // is running in a sandbox, we may only be able to read the value once (before
193 int max_freq = rtc::ReadCpuMaxFreq(); 89 // the sandbox is initialized) and not thereafter.
194 if (max_freq > 0) { 90 // For more information see crbug.com/176522.
195 cpu_speed_ = max_freq / 1000; 91 int SystemInfo::logical_cpus_ = 0;
196 } 92
197 #endif 93 SystemInfo::SystemInfo() {
198 // For L2 CacheSize see also
199 // http://www.flounder.com/cpuid_explorer2.htm#CPUID(0x800000006)
200 #ifdef CPU_X86
201 if (cache_size_ == 0) {
202 int cpu_info[4];
203 __cpuid(cpu_info, 0x80000000); // query maximum extended cpuid function.
204 if (static_cast<uint32>(cpu_info[0]) >= 0x80000006) {
205 __cpuid(cpu_info, 0x80000006);
206 cache_size_ = (cpu_info[2] >> 16) * 1024;
207 }
208 }
209 #endif
210 } 94 }
211 95
212 // Return the number of cpu threads available to the system. 96 // Return the number of cpu threads available to the system.
97 // static
213 int SystemInfo::GetMaxCpus() { 98 int SystemInfo::GetMaxCpus() {
99 if (!logical_cpus_)
100 logical_cpus_ = DetectNumberOfCores();
214 return logical_cpus_; 101 return logical_cpus_;
215 } 102 }
216 103
217 // Return the number of cpu cores available to the system.
218 int SystemInfo::GetMaxPhysicalCpus() {
219 return physical_cpus_;
220 }
221
222 // Return the number of cpus available to the process. Since affinity can be 104 // Return the number of cpus available to the process. Since affinity can be
223 // changed on the fly, do not cache this value. 105 // changed on the fly, do not cache this value.
224 // Can be affected by heat. 106 // Can be affected by heat.
225 int SystemInfo::GetCurCpus() { 107 int SystemInfo::GetCurCpus() {
226 int cur_cpus; 108 int cur_cpus = 0;
227 #if defined(WEBRTC_WIN) 109 #if defined(WEBRTC_WIN)
228 DWORD_PTR process_mask, system_mask; 110 DWORD_PTR process_mask = 0;
111 DWORD_PTR system_mask = 0;
229 ::GetProcessAffinityMask(::GetCurrentProcess(), &process_mask, &system_mask); 112 ::GetProcessAffinityMask(::GetCurrentProcess(), &process_mask, &system_mask);
230 for (cur_cpus = 0; process_mask; ++cur_cpus) { 113 for (int i = 0; i < sizeof(DWORD_PTR) * 8; ++i) {
231 // Sparse-ones algorithm. There are slightly faster methods out there but 114 if (process_mask & 1)
232 // they are unintuitive and won't make a difference on a single dword. 115 ++cur_cpus;
233 process_mask &= (process_mask - 1); 116 process_mask >>= 1;
234 } 117 }
235 #elif defined(WEBRTC_MAC) 118 #elif defined(WEBRTC_MAC)
236 uint32_t sysctl_value; 119 uint32_t sysctl_value;
237 size_t length = sizeof(sysctl_value); 120 size_t length = sizeof(sysctl_value);
238 int error = sysctlbyname("hw.ncpu", &sysctl_value, &length, NULL, 0); 121 int error = sysctlbyname("hw.ncpu", &sysctl_value, &length, NULL, 0);
239 cur_cpus = !error ? static_cast<int>(sysctl_value) : 1; 122 cur_cpus = !error ? static_cast<int>(sysctl_value) : 1;
240 #else 123 #else
241 // Linux, Solaris, WEBRTC_ANDROID 124 // Linux, Solaris, WEBRTC_ANDROID
242 cur_cpus = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); 125 cur_cpus = GetMaxCpus();
243 #endif 126 #endif
244 return cur_cpus; 127 return cur_cpus;
245 } 128 }
246 129
247 // Return the type of this CPU. 130 // Return the type of this CPU.
248 SystemInfo::Architecture SystemInfo::GetCpuArchitecture() { 131 SystemInfo::Architecture SystemInfo::GetCpuArchitecture() {
249 return cpu_arch_; 132 #if defined(__arm__) || defined(_M_ARM)
133 return SI_ARCH_ARM;
134 #elif defined(__x86_64__) || defined(_M_X64)
135 return SI_ARCH_X64;
136 #elif defined(__i386__) || defined(_M_IX86)
137 return SI_ARCH_X86;
138 #else
139 return SI_ARCH_UNKNOWN;
140 #endif
250 } 141 }
251 142
252 // Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD". 143 // Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD".
253 // See "Intel Processor Identification and the CPUID Instruction" 144 // See "Intel Processor Identification and the CPUID Instruction"
254 // (Intel document number: 241618) 145 // (Intel document number: 241618)
255 std::string SystemInfo::GetCpuVendor() { 146 std::string SystemInfo::GetCpuVendor() {
256 if (cpu_vendor_.empty()) {
257 #if defined(CPU_X86) 147 #if defined(CPU_X86)
258 int cpu_info[4]; 148 int cpu_info[4];
259 __cpuid(cpu_info, 0); 149 __cpuid(cpu_info, 0);
260 cpu_info[0] = cpu_info[1]; // Reorder output 150 cpu_info[0] = cpu_info[1]; // Reorder output
261 cpu_info[1] = cpu_info[3]; 151 cpu_info[1] = cpu_info[3];
262 // cpu_info[2] = cpu_info[2]; // Avoid -Werror=self-assign 152 // cpu_info[2] = cpu_info[2]; // Avoid -Werror=self-assign
263 cpu_info[3] = 0; 153 cpu_info[3] = 0;
264 cpu_vendor_ = std::string(reinterpret_cast<char*>(&cpu_info[0])); 154 return std::string(reinterpret_cast<char*>(&cpu_info[0]));
265 #elif defined(CPU_ARM) 155 #elif defined(CPU_ARM)
266 cpu_vendor_ = std::string("ARM"); 156 return "ARM";
267 #else 157 #else
268 cpu_vendor_ = std::string("Undefined"); 158 return "Undefined";
269 #endif
270 }
271 return cpu_vendor_;
272 }
273
274 int SystemInfo::GetCpuCacheSize() {
275 return cache_size_;
276 }
277
278 // Return the "family" of this CPU.
279 int SystemInfo::GetCpuFamily() {
280 return cpu_family_;
281 }
282
283 // Return the "model" of this CPU.
284 int SystemInfo::GetCpuModel() {
285 return cpu_model_;
286 }
287
288 // Return the "stepping" of this CPU.
289 int SystemInfo::GetCpuStepping() {
290 return cpu_stepping_;
291 }
292
293 // Return the clockrate of the primary processor in Mhz. This value can be
294 // cached. Returns -1 on error.
295 int SystemInfo::GetMaxCpuSpeed() {
296 if (cpu_speed_) {
297 return cpu_speed_;
298 }
299 #if defined(WEBRTC_WIN)
300 HKEY key;
301 static const WCHAR keyName[] =
302 L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
303
304 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key)
305 == ERROR_SUCCESS) {
306 DWORD data, len;
307 len = sizeof(data);
308
309 if (RegQueryValueEx(key, L"~Mhz", 0, 0, reinterpret_cast<LPBYTE>(&data),
310 &len) == ERROR_SUCCESS) {
311 cpu_speed_ = data;
312 } else {
313 LOG(LS_WARNING) << "Failed to query registry value HKLM\\" << keyName
314 << "\\~Mhz";
315 cpu_speed_ = -1;
316 }
317
318 RegCloseKey(key);
319 } else {
320 LOG(LS_WARNING) << "Failed to open registry key HKLM\\" << keyName;
321 cpu_speed_ = -1;
322 }
323 #elif defined(WEBRTC_MAC)
324 uint64_t sysctl_value;
325 size_t length = sizeof(sysctl_value);
326 int error = sysctlbyname("hw.cpufrequency_max", &sysctl_value, &length,
327 NULL, 0);
328 cpu_speed_ = !error ? static_cast<int>(sysctl_value/1000000) : -1;
329 #else
330 // TODO(fbarchard): Implement using proc/cpuinfo
331 cpu_speed_ = 0;
332 #endif
333 return cpu_speed_;
334 }
335
336 // Dynamically check the current clockrate, which could be reduced because of
337 // powersaving profiles. Eventually for windows we want to query WMI for
338 // root\WMI::ProcessorPerformance.InstanceName="Processor_Number_0".frequency
339 int SystemInfo::GetCurCpuSpeed() {
340 #if defined(WEBRTC_WIN)
341 // TODO(fbarchard): Add WMI check, requires COM initialization
342 // NOTE(fbarchard): Testable on Sandy Bridge.
343 return GetMaxCpuSpeed();
344 #elif defined(WEBRTC_MAC)
345 uint64_t sysctl_value;
346 size_t length = sizeof(sysctl_value);
347 int error = sysctlbyname("hw.cpufrequency", &sysctl_value, &length, NULL, 0);
348 return !error ? static_cast<int>(sysctl_value/1000000) : GetMaxCpuSpeed();
349 #else // WEBRTC_LINUX
350 // TODO(fbarchard): Use proc/cpuinfo for Cur speed on Linux.
351 return GetMaxCpuSpeed();
352 #endif 159 #endif
353 } 160 }
354 161
355 // Returns the amount of installed physical memory in Bytes. Cacheable. 162 // Returns the amount of installed physical memory in Bytes. Cacheable.
356 // Returns -1 on error. 163 // Returns -1 on error.
357 int64 SystemInfo::GetMemorySize() { 164 int64 SystemInfo::GetMemorySize() {
358 if (memory_) { 165 int64 memory = -1;
359 return memory_;
360 }
361 166
362 #if defined(WEBRTC_WIN) 167 #if defined(WEBRTC_WIN)
363 MEMORYSTATUSEX status = {0}; 168 MEMORYSTATUSEX status = {0};
364 status.dwLength = sizeof(status); 169 status.dwLength = sizeof(status);
365 170
366 if (GlobalMemoryStatusEx(&status)) { 171 if (GlobalMemoryStatusEx(&status)) {
367 memory_ = status.ullTotalPhys; 172 memory = status.ullTotalPhys;
368 } else { 173 } else {
369 LOG_GLE(LS_WARNING) << "GlobalMemoryStatusEx failed."; 174 LOG_GLE(LS_WARNING) << "GlobalMemoryStatusEx failed.";
370 memory_ = -1;
371 } 175 }
372 176
373 #elif defined(WEBRTC_MAC) 177 #elif defined(WEBRTC_MAC)
374 size_t len = sizeof(memory_); 178 size_t len = sizeof(memory);
375 int error = sysctlbyname("hw.memsize", &memory_, &len, NULL, 0); 179 int error = sysctlbyname("hw.memsize", &memory, &len, NULL, 0);
376 if (error || memory_ == 0) { 180 if (error || memory == 0)
377 memory_ = -1; 181 memory = -1;
378 }
379 #else // WEBRTC_LINUX 182 #else // WEBRTC_LINUX
380 memory_ = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) * 183 memory = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) *
381 static_cast<int64>(sysconf(_SC_PAGESIZE)); 184 static_cast<int64>(sysconf(_SC_PAGESIZE));
382 if (memory_ < 0) { 185 if (memory < 0) {
383 LOG(LS_WARNING) << "sysconf(_SC_PHYS_PAGES) failed." 186 LOG(LS_WARNING) << "sysconf(_SC_PHYS_PAGES) failed."
384 << "sysconf(_SC_PHYS_PAGES) " << sysconf(_SC_PHYS_PAGES) 187 << "sysconf(_SC_PHYS_PAGES) " << sysconf(_SC_PHYS_PAGES)
385 << "sysconf(_SC_PAGESIZE) " << sysconf(_SC_PAGESIZE); 188 << "sysconf(_SC_PAGESIZE) " << sysconf(_SC_PAGESIZE);
386 memory_ = -1; 189 memory = -1;
387 } 190 }
388 #endif 191 #endif
389 192
390 return memory_; 193 return memory;
391 } 194 }
392 195
393
394 // Return the name of the machine model we are currently running on. 196 // Return the name of the machine model we are currently running on.
395 // This is a human readable string that consists of the name and version 197 // This is a human readable string that consists of the name and version
396 // number of the hardware, i.e 'MacBookAir1,1'. Returns an empty string if 198 // number of the hardware, i.e 'MacBookAir1,1'. Returns an empty string if
397 // model can not be determined. The string is cached for subsequent calls. 199 // model can not be determined.
398 std::string SystemInfo::GetMachineModel() { 200 std::string SystemInfo::GetMachineModel() {
399 if (!machine_model_.empty()) {
400 return machine_model_;
401 }
402
403 #if defined(WEBRTC_MAC) 201 #if defined(WEBRTC_MAC)
404 char buffer[128]; 202 char buffer[128];
405 size_t length = sizeof(buffer); 203 size_t length = sizeof(buffer);
406 int error = sysctlbyname("hw.model", buffer, &length, NULL, 0); 204 int error = sysctlbyname("hw.model", buffer, &length, NULL, 0);
407 if (!error) { 205 if (!error)
408 machine_model_.assign(buffer, length - 1); 206 return std::string(buffer, length - 1);
409 } else { 207 return std::string();
410 machine_model_.clear();
411 }
412 #else 208 #else
413 machine_model_ = "Not available"; 209 return "Not available";
414 #endif 210 #endif
415
416 return machine_model_;
417 } 211 }
418 212
419 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
420 // Helper functions to query IOKit for video hardware properties.
421 static CFTypeRef SearchForProperty(io_service_t port, CFStringRef name) {
422 return IORegistryEntrySearchCFProperty(port, kIOServicePlane,
423 name, kCFAllocatorDefault,
424 kIORegistryIterateRecursively | kIORegistryIterateParents);
425 }
426
427 static void GetProperty(io_service_t port, CFStringRef name, int* value) {
428 if (!value) return;
429 CFTypeRef ref = SearchForProperty(port, name);
430 if (ref) {
431 CFTypeID refType = CFGetTypeID(ref);
432 if (CFNumberGetTypeID() == refType) {
433 CFNumberRef number = reinterpret_cast<CFNumberRef>(ref);
434 p_convertCFNumberToInt(number, value);
435 } else if (CFDataGetTypeID() == refType) {
436 CFDataRef data = reinterpret_cast<CFDataRef>(ref);
437 if (CFDataGetLength(data) == sizeof(UInt32)) {
438 *value = *reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data));
439 }
440 }
441 CFRelease(ref);
442 }
443 }
444
445 static void GetProperty(io_service_t port, CFStringRef name,
446 std::string* value) {
447 if (!value) return;
448 CFTypeRef ref = SearchForProperty(port, name);
449 if (ref) {
450 CFTypeID refType = CFGetTypeID(ref);
451 if (CFStringGetTypeID() == refType) {
452 CFStringRef stringRef = reinterpret_cast<CFStringRef>(ref);
453 p_convertHostCFStringRefToCPPString(stringRef, *value);
454 } else if (CFDataGetTypeID() == refType) {
455 CFDataRef dataRef = reinterpret_cast<CFDataRef>(ref);
456 *value = std::string(reinterpret_cast<const char*>(
457 CFDataGetBytePtr(dataRef)), CFDataGetLength(dataRef));
458 }
459 CFRelease(ref);
460 }
461 }
462 #endif
463
464 SystemInfo::GpuInfo::GpuInfo() : vendor_id(0), device_id(0) {
465 }
466
467 SystemInfo::GpuInfo::~GpuInfo() = default;
468
469 // Fills a struct with information on the graphics adapater and returns true
470 // iff successful.
471 bool SystemInfo::GetGpuInfo(GpuInfo *info) {
472 if (!info) return false;
473 #if defined(WEBRTC_WIN) && !defined(EXCLUDE_D3D9)
474 D3DADAPTER_IDENTIFIER9 identifier;
475 HRESULT hr = E_FAIL;
476 HINSTANCE d3d_lib = LoadLibrary(L"d3d9.dll");
477
478 if (d3d_lib) {
479 typedef IDirect3D9* (WINAPI *D3DCreate9Proc)(UINT);
480 D3DCreate9Proc d3d_create_proc = reinterpret_cast<D3DCreate9Proc>(
481 GetProcAddress(d3d_lib, "Direct3DCreate9"));
482 if (d3d_create_proc) {
483 IDirect3D9* d3d = d3d_create_proc(D3D_SDK_VERSION);
484 if (d3d) {
485 hr = d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
486 d3d->Release();
487 }
488 }
489 FreeLibrary(d3d_lib);
490 }
491
492 if (hr != D3D_OK) {
493 LOG(LS_ERROR) << "Failed to access Direct3D9 information.";
494 return false;
495 }
496
497 info->device_name = identifier.DeviceName;
498 info->description = identifier.Description;
499 info->vendor_id = identifier.VendorId;
500 info->device_id = identifier.DeviceId;
501 info->driver = identifier.Driver;
502 // driver_version format: product.version.subversion.build
503 std::stringstream ss;
504 ss << HIWORD(identifier.DriverVersion.HighPart) << "."
505 << LOWORD(identifier.DriverVersion.HighPart) << "."
506 << HIWORD(identifier.DriverVersion.LowPart) << "."
507 << LOWORD(identifier.DriverVersion.LowPart);
508 info->driver_version = ss.str();
509 return true;
510 #elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
511 // We'll query the IOKit for the gpu of the main display.
512 io_service_t display_service_port = CGDisplayIOServicePort(
513 kCGDirectMainDisplay);
514 GetProperty(display_service_port, CFSTR("vendor-id"), &info->vendor_id);
515 GetProperty(display_service_port, CFSTR("device-id"), &info->device_id);
516 GetProperty(display_service_port, CFSTR("model"), &info->description);
517 return true;
518 #else // WEBRTC_LINUX
519 // TODO(fbarchard): Implement this on Linux
520 return false;
521 #endif
522 }
523 } // namespace rtc 213 } // namespace rtc
OLDNEW
« no previous file with comments | « webrtc/base/systeminfo.h ('k') | webrtc/base/systeminfo_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698