147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2008 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/systeminfo.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <winsock2.h>
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef EXCLUDE_D3D9
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <d3d9.h>
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <intrin.h>  // for __cpuid()
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <ApplicationServices/ApplicationServices.h>
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <CoreServices/CoreServices.h>
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_LINUX)
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <unistd.h>
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC)
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/sysctl.h>
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/scoped_ptr.h"
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h"
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/macconversion.h"
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_LINUX)
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/linux.h"
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringutils.h"
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// See Also: http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtypedef BOOL (WINAPI *LPFN_GLPI)(
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    PDWORD);
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void GetProcessorInformation(int* physical_cpus, int* cache_size) {
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // GetLogicalProcessorInformation() is available on Windows XP SP3 and beyond.
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LPFN_GLPI glpi = reinterpret_cast<LPFN_GLPI>(GetProcAddress(
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      GetModuleHandle(L"kernel32"),
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      "GetLogicalProcessorInformation"));
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (NULL == glpi) {
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Determine buffer size, allocate and get processor information.
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Size can change between calls (unlikely), so a loop is done.
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD return_length = 0;
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_ptr<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]> infos;
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (!glpi(infos.get(), &return_length)) {
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)]);
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return;
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  *physical_cpus = 0;
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  *cache_size = 0;
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (size_t i = 0;
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      i < return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (infos[i].Relationship == RelationProcessorCore) {
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ++*physical_cpus;
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (infos[i].Relationship == RelationCache) {
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      int next_cache_size = static_cast<int>(infos[i].Cache.Size);
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (next_cache_size >= *cache_size) {
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *cache_size = next_cache_size;
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return;
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO(fbarchard): Use gcc 4.4 provided cpuid intrinsic
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// 32 bit fpic requires ebx be preserved
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic inline void __cpuid(int cpu_info[4], int info_type) {
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  __asm__ volatile (  // NOLINT
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    "mov %%ebx, %%edi\n"
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    "cpuid\n"
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    "xchg %%edi, %%ebx\n"
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : "a"(info_type)
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  );  // NOLINT
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(__i386__) || defined(__x86_64__)
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic inline void __cpuid(int cpu_info[4], int info_type) {
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  __asm__ volatile (  // NOLINT
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    "cpuid\n"
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : "a"(info_type)
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  );  // NOLINT
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // WEBRTC_WIN
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Note(fbarchard):
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Family and model are extended family and extended model.  8 bits each.
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSystemInfo::SystemInfo()
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : physical_cpus_(1), logical_cpus_(1), cache_size_(0),
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cpu_family_(0), cpu_model_(0), cpu_stepping_(0),
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cpu_speed_(0), memory_(0) {
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Initialize the basic information.
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(__arm__) || defined(_M_ARM)
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_arch_ = SI_ARCH_ARM;
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(__x86_64__) || defined(_M_X64)
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_arch_ = SI_ARCH_X64;
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(__i386__) || defined(_M_IX86)
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_arch_ = SI_ARCH_X86;
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_arch_ = SI_ARCH_UNKNOWN;
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SYSTEM_INFO si;
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  GetSystemInfo(&si);
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  logical_cpus_ = si.dwNumberOfProcessors;
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  GetProcessorInformation(&physical_cpus_, &cache_size_);
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (physical_cpus_ <= 0) {
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    physical_cpus_ = logical_cpus_;
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_family_ = si.wProcessorLevel;
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_model_ = si.wProcessorRevision >> 8;
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_stepping_ = si.wProcessorRevision & 0xFF;
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint32_t sysctl_value;
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = sizeof(sysctl_value);
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!sysctlbyname("hw.physicalcpu_max", &sysctl_value, &length, NULL, 0)) {
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    physical_cpus_ = static_cast<int>(sysctl_value);
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  length = sizeof(sysctl_value);
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!sysctlbyname("hw.logicalcpu_max", &sysctl_value, &length, NULL, 0)) {
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    logical_cpus_ = static_cast<int>(sysctl_value);
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint64_t sysctl_value64;
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  length = sizeof(sysctl_value64);
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!sysctlbyname("hw.l3cachesize", &sysctl_value64, &length, NULL, 0)) {
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cache_size_ = static_cast<int>(sysctl_value64);
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!cache_size_) {
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    length = sizeof(sysctl_value64);
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!sysctlbyname("hw.l2cachesize", &sysctl_value64, &length, NULL, 0)) {
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cache_size_ = static_cast<int>(sysctl_value64);
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  length = sizeof(sysctl_value);
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!sysctlbyname("machdep.cpu.family", &sysctl_value, &length, NULL, 0)) {
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_family_ = static_cast<int>(sysctl_value);
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  length = sizeof(sysctl_value);
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!sysctlbyname("machdep.cpu.model", &sysctl_value, &length, NULL, 0)) {
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_model_ = static_cast<int>(sysctl_value);
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  length = sizeof(sysctl_value);
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) {
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_stepping_ = static_cast<int>(sysctl_value);
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(__native_client__)
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO(ryanpetrie): Implement this via PPAPI when it's available.
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else  // WEBRTC_LINUX
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ProcCpuInfo proc_info;
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (proc_info.LoadFromSystem()) {
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetNumCpus(&logical_cpus_);
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetNumPhysicalCpus(&physical_cpus_);
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetCpuFamily(&cpu_family_);
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(CPU_X86)
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // These values only apply to x86 systems.
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetSectionIntValue(0, "model", &cpu_model_);
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetSectionIntValue(0, "stepping", &cpu_stepping_);
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetSectionIntValue(0, "cpu MHz", &cpu_speed_);
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    proc_info.GetSectionIntValue(0, "cache size", &cache_size_);
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cache_size_ *= 1024;
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // ProcCpuInfo reads cpu speed from "cpu MHz" under /proc/cpuinfo.
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // But that number is a moving target which can change on-the-fly according to
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // many factors including system workload.
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // See /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors.
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // The one in /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq is more
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // accurate. We use it as our cpu speed when it is available.
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // cpuinfo_max_freq is measured in KHz and requires conversion to MHz.
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int max_freq = rtc::ReadCpuMaxFreq();
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (max_freq > 0) {
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_speed_ = max_freq / 1000;
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// For L2 CacheSize see also
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// http://www.flounder.com/cpuid_explorer2.htm#CPUID(0x800000006)
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef CPU_X86
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (cache_size_ == 0) {
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int cpu_info[4];
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    __cpuid(cpu_info, 0x80000000);  // query maximum extended cpuid function.
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (static_cast<uint32>(cpu_info[0]) >= 0x80000006) {
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      __cpuid(cpu_info, 0x80000006);
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cache_size_ = (cpu_info[2] >> 16) * 1024;
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the number of cpu threads available to the system.
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetMaxCpus() {
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return logical_cpus_;
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the number of cpu cores available to the system.
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetMaxPhysicalCpus() {
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return physical_cpus_;
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the number of cpus available to the process.  Since affinity can be
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// changed on the fly, do not cache this value.
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Can be affected by heat.
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetCurCpus() {
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int cur_cpus;
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD_PTR process_mask, system_mask;
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ::GetProcessAffinityMask(::GetCurrentProcess(), &process_mask, &system_mask);
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (cur_cpus = 0; process_mask; ++cur_cpus) {
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Sparse-ones algorithm. There are slightly faster methods out there but
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // they are unintuitive and won't make a difference on a single dword.
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    process_mask &= (process_mask - 1);
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint32_t sysctl_value;
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = sizeof(sysctl_value);
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error = sysctlbyname("hw.ncpu", &sysctl_value, &length, NULL, 0);
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cur_cpus = !error ? static_cast<int>(sysctl_value) : 1;
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Linux, Solaris, WEBRTC_ANDROID
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cur_cpus = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cur_cpus;
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the type of this CPU.
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSystemInfo::Architecture SystemInfo::GetCpuArchitecture() {
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cpu_arch_;
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD".
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// See "Intel Processor Identification and the CPUID Instruction"
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// (Intel document number: 241618)
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SystemInfo::GetCpuVendor() {
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (cpu_vendor_.empty()) {
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(CPU_X86)
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int cpu_info[4];
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    __cpuid(cpu_info, 0);
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_info[0] = cpu_info[1];  // Reorder output
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_info[1] = cpu_info[3];
2622070e208617a6088da620b7b16203a903eae342candresp@webrtc.org    // cpu_info[2] = cpu_info[2];  // Avoid -Werror=self-assign
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_info[3] = 0;
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_vendor_ = std::string(reinterpret_cast<char*>(&cpu_info[0]));
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(CPU_ARM)
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_vendor_ = std::string("ARM");
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_vendor_ = std::string("Undefined");
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cpu_vendor_;
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetCpuCacheSize() {
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cache_size_;
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the "family" of this CPU.
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetCpuFamily() {
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cpu_family_;
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the "model" of this CPU.
28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetCpuModel() {
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cpu_model_;
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the "stepping" of this CPU.
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetCpuStepping() {
29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cpu_stepping_;
29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the clockrate of the primary processor in Mhz.  This value can be
29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// cached.  Returns -1 on error.
29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetMaxCpuSpeed() {
29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (cpu_speed_) {
29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return cpu_speed_;
29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HKEY key;
30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  static const WCHAR keyName[] =
30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key)
30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      == ERROR_SUCCESS) {
30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    DWORD data, len;
30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    len = sizeof(data);
30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (RegQueryValueEx(key, L"~Mhz", 0, 0, reinterpret_cast<LPBYTE>(&data),
31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        &len) == ERROR_SUCCESS) {
31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cpu_speed_ = data;
31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "Failed to query registry value HKLM\\" << keyName
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                      << "\\~Mhz";
31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      cpu_speed_ = -1;
31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    RegCloseKey(key);
31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "Failed to open registry key HKLM\\" << keyName;
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    cpu_speed_ = -1;
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint64_t sysctl_value;
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = sizeof(sysctl_value);
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error = sysctlbyname("hw.cpufrequency_max", &sysctl_value, &length,
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                           NULL, 0);
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_speed_ = !error ? static_cast<int>(sysctl_value/1000000) : -1;
32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO(fbarchard): Implement using proc/cpuinfo
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cpu_speed_ = 0;
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cpu_speed_;
33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Dynamically check the current clockrate, which could be reduced because of
33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// powersaving profiles.  Eventually for windows we want to query WMI for
33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// root\WMI::ProcessorPerformance.InstanceName="Processor_Number_0".frequency
33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SystemInfo::GetCurCpuSpeed() {
34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO(fbarchard): Add WMI check, requires COM initialization
34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // NOTE(fbarchard): Testable on Sandy Bridge.
34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return GetMaxCpuSpeed();
34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint64_t sysctl_value;
34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = sizeof(sysctl_value);
34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error = sysctlbyname("hw.cpufrequency", &sysctl_value, &length, NULL, 0);
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return !error ? static_cast<int>(sysctl_value/1000000) : GetMaxCpuSpeed();
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else  // WEBRTC_LINUX
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO(fbarchard): Use proc/cpuinfo for Cur speed on Linux.
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return GetMaxCpuSpeed();
35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Returns the amount of installed physical memory in Bytes.  Cacheable.
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Returns -1 on error.
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint64 SystemInfo::GetMemorySize() {
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (memory_) {
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return memory_;
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  MEMORYSTATUSEX status = {0};
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  status.dwLength = sizeof(status);
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (GlobalMemoryStatusEx(&status)) {
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memory_ = status.ullTotalPhys;
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_GLE(LS_WARNING) << "GlobalMemoryStatusEx failed.";
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memory_ = -1;
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t len = sizeof(memory_);
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error = sysctlbyname("hw.memsize", &memory_, &len, NULL, 0);
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (error || memory_ == 0) {
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memory_ = -1;
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else  // WEBRTC_LINUX
38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  memory_ = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) *
38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      static_cast<int64>(sysconf(_SC_PAGESIZE));
38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (memory_ < 0) {
38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "sysconf(_SC_PHYS_PAGES) failed."
38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    << "sysconf(_SC_PHYS_PAGES) " << sysconf(_SC_PHYS_PAGES)
38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    << "sysconf(_SC_PAGESIZE) " << sysconf(_SC_PAGESIZE);
38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    memory_ = -1;
38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return memory_;
39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Return the name of the machine model we are currently running on.
39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This is a human readable string that consists of the name and version
39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// number of the hardware, i.e 'MacBookAir1,1'. Returns an empty string if
39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// model can not be determined. The string is cached for subsequent calls.
39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SystemInfo::GetMachineModel() {
39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!machine_model_.empty()) {
40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return machine_model_;
40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC)
40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char buffer[128];
40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t length = sizeof(buffer);
40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error = sysctlbyname("hw.model", buffer, &length, NULL, 0);
40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!error) {
40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    machine_model_.assign(buffer, length - 1);
40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    machine_model_.clear();
41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  machine_model_ = "Not available";
41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return machine_model_;
41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Helper functions to query IOKit for video hardware properties.
42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic CFTypeRef SearchForProperty(io_service_t port, CFStringRef name) {
42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IORegistryEntrySearchCFProperty(port, kIOServicePlane,
42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      name, kCFAllocatorDefault,
42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      kIORegistryIterateRecursively | kIORegistryIterateParents);
42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void GetProperty(io_service_t port, CFStringRef name, int* value) {
42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!value) return;
42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CFTypeRef ref = SearchForProperty(port, name);
43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ref) {
43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CFTypeID refType = CFGetTypeID(ref);
43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (CFNumberGetTypeID() == refType) {
43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CFNumberRef number = reinterpret_cast<CFNumberRef>(ref);
43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      p_convertCFNumberToInt(number, value);
43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (CFDataGetTypeID() == refType) {
43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CFDataRef data = reinterpret_cast<CFDataRef>(ref);
43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (CFDataGetLength(data) == sizeof(UInt32)) {
43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        *value = *reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data));
43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CFRelease(ref);
44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void GetProperty(io_service_t port, CFStringRef name,
44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        std::string* value) {
44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!value) return;
44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CFTypeRef ref = SearchForProperty(port, name);
44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ref) {
45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CFTypeID refType = CFGetTypeID(ref);
45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (CFStringGetTypeID() == refType) {
45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CFStringRef stringRef = reinterpret_cast<CFStringRef>(ref);
45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      p_convertHostCFStringRefToCPPString(stringRef, *value);
45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (CFDataGetTypeID() == refType) {
45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CFDataRef dataRef = reinterpret_cast<CFDataRef>(ref);
45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *value = std::string(reinterpret_cast<const char*>(
45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          CFDataGetBytePtr(dataRef)), CFDataGetLength(dataRef));
45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CFRelease(ref);
46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Fills a struct with information on the graphics adapater and returns true
46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// iff successful.
46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SystemInfo::GetGpuInfo(GpuInfo *info) {
46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!info) return false;
46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN) && !defined(EXCLUDE_D3D9)
46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  D3DADAPTER_IDENTIFIER9 identifier;
47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HRESULT hr = E_FAIL;
47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HINSTANCE d3d_lib = LoadLibrary(L"d3d9.dll");
47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (d3d_lib) {
47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    typedef IDirect3D9* (WINAPI *D3DCreate9Proc)(UINT);
47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    D3DCreate9Proc d3d_create_proc = reinterpret_cast<D3DCreate9Proc>(
47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        GetProcAddress(d3d_lib, "Direct3DCreate9"));
47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (d3d_create_proc) {
47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      IDirect3D9* d3d = d3d_create_proc(D3D_SDK_VERSION);
47947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (d3d) {
48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        hr = d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        d3d->Release();
48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    FreeLibrary(d3d_lib);
48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (hr != D3D_OK) {
48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_ERROR) << "Failed to access Direct3D9 information.";
48947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
49147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info->device_name = identifier.DeviceName;
49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info->description = identifier.Description;
49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info->vendor_id = identifier.VendorId;
49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info->device_id = identifier.DeviceId;
49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info->driver = identifier.Driver;
49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // driver_version format: product.version.subversion.build
49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::stringstream ss;
49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ss << HIWORD(identifier.DriverVersion.HighPart) << "."
50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org     << LOWORD(identifier.DriverVersion.HighPart) << "."
50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org     << HIWORD(identifier.DriverVersion.LowPart) << "."
50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org     << LOWORD(identifier.DriverVersion.LowPart);
50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info->driver_version = ss.str();
50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // We'll query the IOKit for the gpu of the main display.
50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  io_service_t display_service_port = CGDisplayIOServicePort(
50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      kCGDirectMainDisplay);
50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  GetProperty(display_service_port, CFSTR("vendor-id"), &info->vendor_id);
51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  GetProperty(display_service_port, CFSTR("device-id"), &info->device_id);
51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  GetProperty(display_service_port, CFSTR("model"), &info->description);
51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else  // WEBRTC_LINUX
51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO(fbarchard): Implement this on Linux
51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return false;
51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
519