| /* |
| * 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 (size_t 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_t SystemInfo::GetMemorySize() { |
| int64_t 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; |
| #elif defined(WEBRTC_LINUX) |
| memory = static_cast<int64_t>(sysconf(_SC_PHYS_PAGES)) * |
| static_cast<int64_t>(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 |