This cl removes a lot of unused functionality in SystemInfo and reduces dependencies. There's duplicate functionality in this class and WebRTC's CpuInfo class, so I'm consolidating the two implementations. The CpuInfo interface will still exist since it's being used from Chrome to initialize the core count before the sandbox is engaged. With this change, the SystemInfo class will get the benefit too of this initialization. NOTRY=true (using no try due to a dead android try bot) Review URL: https://codereview.webrtc.org/1286163003 Cr-Commit-Position: refs/heads/master@{#9743}
214 lines
6.3 KiB
C++
214 lines
6.3 KiB
C++
/*
|
|
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/base/systeminfo.h"
|
|
|
|
#if defined(WEBRTC_WIN)
|
|
#include <winsock2.h>
|
|
#include <windows.h>
|
|
#ifndef EXCLUDE_D3D9
|
|
#include <d3d9.h>
|
|
#endif
|
|
#include <intrin.h> // for __cpuid()
|
|
#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
|
#include <ApplicationServices/ApplicationServices.h>
|
|
#include <CoreServices/CoreServices.h>
|
|
#elif defined(WEBRTC_LINUX)
|
|
#include <unistd.h>
|
|
#endif
|
|
#if defined(WEBRTC_MAC)
|
|
#include <sys/sysctl.h>
|
|
#endif
|
|
|
|
#include "webrtc/base/common.h"
|
|
#include "webrtc/base/logging.h"
|
|
#include "webrtc/base/stringutils.h"
|
|
|
|
namespace rtc {
|
|
|
|
// See Also: http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx
|
|
#if !defined(WEBRTC_WIN)
|
|
// TODO(fbarchard): Use gcc 4.4 provided cpuid intrinsic
|
|
// 32 bit fpic requires ebx be preserved
|
|
#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
|
|
static inline void __cpuid(int cpu_info[4], int info_type) {
|
|
__asm__ volatile ( // NOLINT
|
|
"mov %%ebx, %%edi\n"
|
|
"cpuid\n"
|
|
"xchg %%edi, %%ebx\n"
|
|
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
|
: "a"(info_type)
|
|
); // NOLINT
|
|
}
|
|
#elif defined(__i386__) || defined(__x86_64__)
|
|
static inline void __cpuid(int cpu_info[4], int info_type) {
|
|
__asm__ volatile ( // NOLINT
|
|
"cpuid\n"
|
|
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
|
: "a"(info_type)
|
|
); // NOLINT
|
|
}
|
|
#endif
|
|
#endif // WEBRTC_WIN
|
|
|
|
static int DetectNumberOfCores() {
|
|
// We fall back on assuming a single core in case of errors.
|
|
int number_of_cores = 1;
|
|
|
|
#if defined(WEBRTC_WIN)
|
|
SYSTEM_INFO si;
|
|
GetSystemInfo(&si);
|
|
number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
|
|
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
|
|
number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
|
|
#elif defined(WEBRTC_MAC)
|
|
int name[] = {CTL_HW, HW_AVAILCPU};
|
|
size_t size = sizeof(number_of_cores);
|
|
if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) {
|
|
LOG(LS_ERROR) << "Failed to get number of cores";
|
|
number_of_cores = 1;
|
|
}
|
|
#else
|
|
LOG(LS_ERROR) << "No function to get number of cores";
|
|
#endif
|
|
|
|
LOG(LS_INFO) << "Available number of cores: " << number_of_cores;
|
|
|
|
return number_of_cores;
|
|
}
|
|
|
|
// Statically cache the number of system cores available since if the process
|
|
// is running in a sandbox, we may only be able to read the value once (before
|
|
// the sandbox is initialized) and not thereafter.
|
|
// For more information see crbug.com/176522.
|
|
int SystemInfo::logical_cpus_ = 0;
|
|
|
|
SystemInfo::SystemInfo() {
|
|
}
|
|
|
|
// Return the number of cpu threads available to the system.
|
|
// static
|
|
int SystemInfo::GetMaxCpus() {
|
|
if (!logical_cpus_)
|
|
logical_cpus_ = DetectNumberOfCores();
|
|
return logical_cpus_;
|
|
}
|
|
|
|
// Return the number of cpus available to the process. Since affinity can be
|
|
// changed on the fly, do not cache this value.
|
|
// Can be affected by heat.
|
|
int SystemInfo::GetCurCpus() {
|
|
int cur_cpus = 0;
|
|
#if defined(WEBRTC_WIN)
|
|
DWORD_PTR process_mask = 0;
|
|
DWORD_PTR system_mask = 0;
|
|
::GetProcessAffinityMask(::GetCurrentProcess(), &process_mask, &system_mask);
|
|
for (int i = 0; i < sizeof(DWORD_PTR) * 8; ++i) {
|
|
if (process_mask & 1)
|
|
++cur_cpus;
|
|
process_mask >>= 1;
|
|
}
|
|
#elif defined(WEBRTC_MAC)
|
|
uint32_t sysctl_value;
|
|
size_t length = sizeof(sysctl_value);
|
|
int error = sysctlbyname("hw.ncpu", &sysctl_value, &length, NULL, 0);
|
|
cur_cpus = !error ? static_cast<int>(sysctl_value) : 1;
|
|
#else
|
|
// Linux, Solaris, WEBRTC_ANDROID
|
|
cur_cpus = GetMaxCpus();
|
|
#endif
|
|
return cur_cpus;
|
|
}
|
|
|
|
// Return the type of this CPU.
|
|
SystemInfo::Architecture SystemInfo::GetCpuArchitecture() {
|
|
#if defined(__arm__) || defined(_M_ARM)
|
|
return SI_ARCH_ARM;
|
|
#elif defined(__x86_64__) || defined(_M_X64)
|
|
return SI_ARCH_X64;
|
|
#elif defined(__i386__) || defined(_M_IX86)
|
|
return SI_ARCH_X86;
|
|
#else
|
|
return SI_ARCH_UNKNOWN;
|
|
#endif
|
|
}
|
|
|
|
// Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD".
|
|
// See "Intel Processor Identification and the CPUID Instruction"
|
|
// (Intel document number: 241618)
|
|
std::string SystemInfo::GetCpuVendor() {
|
|
#if defined(CPU_X86)
|
|
int cpu_info[4];
|
|
__cpuid(cpu_info, 0);
|
|
cpu_info[0] = cpu_info[1]; // Reorder output
|
|
cpu_info[1] = cpu_info[3];
|
|
// cpu_info[2] = cpu_info[2]; // Avoid -Werror=self-assign
|
|
cpu_info[3] = 0;
|
|
return std::string(reinterpret_cast<char*>(&cpu_info[0]));
|
|
#elif defined(CPU_ARM)
|
|
return "ARM";
|
|
#else
|
|
return "Undefined";
|
|
#endif
|
|
}
|
|
|
|
// Returns the amount of installed physical memory in Bytes. Cacheable.
|
|
// Returns -1 on error.
|
|
int64 SystemInfo::GetMemorySize() {
|
|
int64 memory = -1;
|
|
|
|
#if defined(WEBRTC_WIN)
|
|
MEMORYSTATUSEX status = {0};
|
|
status.dwLength = sizeof(status);
|
|
|
|
if (GlobalMemoryStatusEx(&status)) {
|
|
memory = status.ullTotalPhys;
|
|
} else {
|
|
LOG_GLE(LS_WARNING) << "GlobalMemoryStatusEx failed.";
|
|
}
|
|
|
|
#elif defined(WEBRTC_MAC)
|
|
size_t len = sizeof(memory);
|
|
int error = sysctlbyname("hw.memsize", &memory, &len, NULL, 0);
|
|
if (error || memory == 0)
|
|
memory = -1;
|
|
#else // WEBRTC_LINUX
|
|
memory = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) *
|
|
static_cast<int64>(sysconf(_SC_PAGESIZE));
|
|
if (memory < 0) {
|
|
LOG(LS_WARNING) << "sysconf(_SC_PHYS_PAGES) failed."
|
|
<< "sysconf(_SC_PHYS_PAGES) " << sysconf(_SC_PHYS_PAGES)
|
|
<< "sysconf(_SC_PAGESIZE) " << sysconf(_SC_PAGESIZE);
|
|
memory = -1;
|
|
}
|
|
#endif
|
|
|
|
return memory;
|
|
}
|
|
|
|
// Return the name of the machine model we are currently running on.
|
|
// This is a human readable string that consists of the name and version
|
|
// number of the hardware, i.e 'MacBookAir1,1'. Returns an empty string if
|
|
// model can not be determined.
|
|
std::string SystemInfo::GetMachineModel() {
|
|
#if defined(WEBRTC_MAC)
|
|
char buffer[128];
|
|
size_t length = sizeof(buffer);
|
|
int error = sysctlbyname("hw.model", buffer, &length, NULL, 0);
|
|
if (!error)
|
|
return std::string(buffer, length - 1);
|
|
return std::string();
|
|
#else
|
|
return "Not available";
|
|
#endif
|
|
}
|
|
|
|
} // namespace rtc
|