blob: 1dc6a682e90e7ab88a092cb665924424d421c543 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2008 The WebRTC Project Authors. All rights reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/systeminfo.h"
12
13#if defined(WEBRTC_WIN)
14#include <winsock2.h>
tommiefefda62015-08-20 05:04:09 -070015#include <windows.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000016#ifndef EXCLUDE_D3D9
17#include <d3d9.h>
18#endif
19#include <intrin.h> // for __cpuid()
20#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
21#include <ApplicationServices/ApplicationServices.h>
22#include <CoreServices/CoreServices.h>
23#elif defined(WEBRTC_LINUX)
24#include <unistd.h>
25#endif
26#if defined(WEBRTC_MAC)
27#include <sys/sysctl.h>
28#endif
29
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030#include "webrtc/base/common.h"
31#include "webrtc/base/logging.h"
32#include "webrtc/base/stringutils.h"
33
34namespace rtc {
35
36// See Also: http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx
tommiefefda62015-08-20 05:04:09 -070037#if !defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000038// TODO(fbarchard): Use gcc 4.4 provided cpuid intrinsic
39// 32 bit fpic requires ebx be preserved
40#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
41static inline void __cpuid(int cpu_info[4], int info_type) {
42 __asm__ volatile ( // NOLINT
43 "mov %%ebx, %%edi\n"
44 "cpuid\n"
45 "xchg %%edi, %%ebx\n"
46 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
47 : "a"(info_type)
48 ); // NOLINT
49}
50#elif defined(__i386__) || defined(__x86_64__)
51static inline void __cpuid(int cpu_info[4], int info_type) {
52 __asm__ volatile ( // NOLINT
53 "cpuid\n"
54 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
55 : "a"(info_type)
56 ); // NOLINT
57}
58#endif
tommiefefda62015-08-20 05:04:09 -070059#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060
tommiefefda62015-08-20 05:04:09 -070061static int DetectNumberOfCores() {
62 // We fall back on assuming a single core in case of errors.
63 int number_of_cores = 1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000064
65#if defined(WEBRTC_WIN)
66 SYSTEM_INFO si;
67 GetSystemInfo(&si);
tommiefefda62015-08-20 05:04:09 -070068 number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
69#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
70 number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000071#elif defined(WEBRTC_MAC)
tommiefefda62015-08-20 05:04:09 -070072 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;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000077 }
tommiefefda62015-08-20 05:04:09 -070078#else
79 LOG(LS_ERROR) << "No function to get number of cores";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000080#endif
tommiefefda62015-08-20 05:04:09 -070081
82 LOG(LS_INFO) << "Available number of cores: " << number_of_cores;
83
84 return number_of_cores;
85}
86
87// Statically cache the number of system cores available since if the process
88// is running in a sandbox, we may only be able to read the value once (before
89// the sandbox is initialized) and not thereafter.
90// For more information see crbug.com/176522.
91int SystemInfo::logical_cpus_ = 0;
92
93SystemInfo::SystemInfo() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000094}
95
96// Return the number of cpu threads available to the system.
tommiefefda62015-08-20 05:04:09 -070097// static
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000098int SystemInfo::GetMaxCpus() {
tommiefefda62015-08-20 05:04:09 -070099 if (!logical_cpus_)
100 logical_cpus_ = DetectNumberOfCores();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000101 return logical_cpus_;
102}
103
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000104// Return the number of cpus available to the process. Since affinity can be
105// changed on the fly, do not cache this value.
106// Can be affected by heat.
107int SystemInfo::GetCurCpus() {
tommiefefda62015-08-20 05:04:09 -0700108 int cur_cpus = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000109#if defined(WEBRTC_WIN)
tommiefefda62015-08-20 05:04:09 -0700110 DWORD_PTR process_mask = 0;
111 DWORD_PTR system_mask = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000112 ::GetProcessAffinityMask(::GetCurrentProcess(), &process_mask, &system_mask);
tommiefefda62015-08-20 05:04:09 -0700113 for (int i = 0; i < sizeof(DWORD_PTR) * 8; ++i) {
114 if (process_mask & 1)
115 ++cur_cpus;
116 process_mask >>= 1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000117 }
118#elif defined(WEBRTC_MAC)
119 uint32_t sysctl_value;
120 size_t length = sizeof(sysctl_value);
121 int error = sysctlbyname("hw.ncpu", &sysctl_value, &length, NULL, 0);
122 cur_cpus = !error ? static_cast<int>(sysctl_value) : 1;
123#else
124 // Linux, Solaris, WEBRTC_ANDROID
tommiefefda62015-08-20 05:04:09 -0700125 cur_cpus = GetMaxCpus();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000126#endif
127 return cur_cpus;
128}
129
130// Return the type of this CPU.
131SystemInfo::Architecture SystemInfo::GetCpuArchitecture() {
tommiefefda62015-08-20 05:04:09 -0700132#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
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000141}
142
143// Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD".
144// See "Intel Processor Identification and the CPUID Instruction"
145// (Intel document number: 241618)
146std::string SystemInfo::GetCpuVendor() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000147#if defined(CPU_X86)
tommiefefda62015-08-20 05:04:09 -0700148 int cpu_info[4];
149 __cpuid(cpu_info, 0);
150 cpu_info[0] = cpu_info[1]; // Reorder output
151 cpu_info[1] = cpu_info[3];
152 // cpu_info[2] = cpu_info[2]; // Avoid -Werror=self-assign
153 cpu_info[3] = 0;
154 return std::string(reinterpret_cast<char*>(&cpu_info[0]));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000155#elif defined(CPU_ARM)
tommiefefda62015-08-20 05:04:09 -0700156 return "ARM";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000157#else
tommiefefda62015-08-20 05:04:09 -0700158 return "Undefined";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000159#endif
160}
161
162// Returns the amount of installed physical memory in Bytes. Cacheable.
163// Returns -1 on error.
164int64 SystemInfo::GetMemorySize() {
tommiefefda62015-08-20 05:04:09 -0700165 int64 memory = -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000166
167#if defined(WEBRTC_WIN)
168 MEMORYSTATUSEX status = {0};
169 status.dwLength = sizeof(status);
170
171 if (GlobalMemoryStatusEx(&status)) {
tommiefefda62015-08-20 05:04:09 -0700172 memory = status.ullTotalPhys;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000173 } else {
174 LOG_GLE(LS_WARNING) << "GlobalMemoryStatusEx failed.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000175 }
176
177#elif defined(WEBRTC_MAC)
tommiefefda62015-08-20 05:04:09 -0700178 size_t len = sizeof(memory);
179 int error = sysctlbyname("hw.memsize", &memory, &len, NULL, 0);
180 if (error || memory == 0)
181 memory = -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000182#else // WEBRTC_LINUX
tommiefefda62015-08-20 05:04:09 -0700183 memory = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) *
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000184 static_cast<int64>(sysconf(_SC_PAGESIZE));
tommiefefda62015-08-20 05:04:09 -0700185 if (memory < 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000186 LOG(LS_WARNING) << "sysconf(_SC_PHYS_PAGES) failed."
187 << "sysconf(_SC_PHYS_PAGES) " << sysconf(_SC_PHYS_PAGES)
188 << "sysconf(_SC_PAGESIZE) " << sysconf(_SC_PAGESIZE);
tommiefefda62015-08-20 05:04:09 -0700189 memory = -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000190 }
191#endif
192
tommiefefda62015-08-20 05:04:09 -0700193 return memory;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000194}
195
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000196// Return the name of the machine model we are currently running on.
197// This is a human readable string that consists of the name and version
198// number of the hardware, i.e 'MacBookAir1,1'. Returns an empty string if
tommiefefda62015-08-20 05:04:09 -0700199// model can not be determined.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000200std::string SystemInfo::GetMachineModel() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000201#if defined(WEBRTC_MAC)
202 char buffer[128];
203 size_t length = sizeof(buffer);
204 int error = sysctlbyname("hw.model", buffer, &length, NULL, 0);
tommiefefda62015-08-20 05:04:09 -0700205 if (!error)
206 return std::string(buffer, length - 1);
207 return std::string();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000208#else
tommiefefda62015-08-20 05:04:09 -0700209 return "Not available";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000210#endif
211}
tommiefefda62015-08-20 05:04:09 -0700212
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000213} // namespace rtc