summaryrefslogtreecommitdiff
path: root/third-party/benchmark/src/sysinfo.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third-party/benchmark/src/sysinfo.cc')
-rw-r--r--third-party/benchmark/src/sysinfo.cc726
1 files changed, 0 insertions, 726 deletions
diff --git a/third-party/benchmark/src/sysinfo.cc b/third-party/benchmark/src/sysinfo.cc
deleted file mode 100644
index c1969ea2d3fe..000000000000
--- a/third-party/benchmark/src/sysinfo.cc
+++ /dev/null
@@ -1,726 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include <shlwapi.h>
-#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
-#include <versionhelpers.h>
-#include <windows.h>
-#include <codecvt>
-#else
-#include <fcntl.h>
-#ifndef BENCHMARK_OS_FUCHSIA
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
-#include <unistd.h>
-#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \
- defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD || \
- defined BENCHMARK_OS_DRAGONFLY
-#define BENCHMARK_HAS_SYSCTL
-#include <sys/sysctl.h>
-#endif
-#endif
-#if defined(BENCHMARK_OS_SOLARIS)
-#include <kstat.h>
-#endif
-#if defined(BENCHMARK_OS_QNX)
-#include <sys/syspage.h>
-#endif
-
-#include <algorithm>
-#include <array>
-#include <bitset>
-#include <cerrno>
-#include <climits>
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <sstream>
-#include <locale>
-#include <utility>
-
-#include "check.h"
-#include "cycleclock.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "sleep.h"
-#include "string_util.h"
-
-namespace benchmark {
-namespace {
-
-void PrintImp(std::ostream& out) { out << std::endl; }
-
-template <class First, class... Rest>
-void PrintImp(std::ostream& out, First&& f, Rest&&... rest) {
- out << std::forward<First>(f);
- PrintImp(out, std::forward<Rest>(rest)...);
-}
-
-template <class... Args>
-BENCHMARK_NORETURN void PrintErrorAndDie(Args&&... args) {
- PrintImp(std::cerr, std::forward<Args>(args)...);
- std::exit(EXIT_FAILURE);
-}
-
-#ifdef BENCHMARK_HAS_SYSCTL
-
-/// ValueUnion - A type used to correctly alias the byte-for-byte output of
-/// `sysctl` with the result type it's to be interpreted as.
-struct ValueUnion {
- union DataT {
- uint32_t uint32_value;
- uint64_t uint64_value;
- // For correct aliasing of union members from bytes.
- char bytes[8];
- };
- using DataPtr = std::unique_ptr<DataT, decltype(&std::free)>;
-
- // The size of the data union member + its trailing array size.
- size_t Size;
- DataPtr Buff;
-
- public:
- ValueUnion() : Size(0), Buff(nullptr, &std::free) {}
-
- explicit ValueUnion(size_t BuffSize)
- : Size(sizeof(DataT) + BuffSize),
- Buff(::new (std::malloc(Size)) DataT(), &std::free) {}
-
- ValueUnion(ValueUnion&& other) = default;
-
- explicit operator bool() const { return bool(Buff); }
-
- char* data() const { return Buff->bytes; }
-
- std::string GetAsString() const { return std::string(data()); }
-
- int64_t GetAsInteger() const {
- if (Size == sizeof(Buff->uint32_value))
- return static_cast<int32_t>(Buff->uint32_value);
- else if (Size == sizeof(Buff->uint64_value))
- return static_cast<int64_t>(Buff->uint64_value);
- BENCHMARK_UNREACHABLE();
- }
-
- uint64_t GetAsUnsigned() const {
- if (Size == sizeof(Buff->uint32_value))
- return Buff->uint32_value;
- else if (Size == sizeof(Buff->uint64_value))
- return Buff->uint64_value;
- BENCHMARK_UNREACHABLE();
- }
-
- template <class T, int N>
- std::array<T, N> GetAsArray() {
- const int ArrSize = sizeof(T) * N;
- CHECK_LE(ArrSize, Size);
- std::array<T, N> Arr;
- std::memcpy(Arr.data(), data(), ArrSize);
- return Arr;
- }
-};
-
-ValueUnion GetSysctlImp(std::string const& Name) {
-#if defined BENCHMARK_OS_OPENBSD
- int mib[2];
-
- mib[0] = CTL_HW;
- if ((Name == "hw.ncpu") || (Name == "hw.cpuspeed")){
- ValueUnion buff(sizeof(int));
-
- if (Name == "hw.ncpu") {
- mib[1] = HW_NCPU;
- } else {
- mib[1] = HW_CPUSPEED;
- }
-
- if (sysctl(mib, 2, buff.data(), &buff.Size, nullptr, 0) == -1) {
- return ValueUnion();
- }
- return buff;
- }
- return ValueUnion();
-#else
- size_t CurBuffSize = 0;
- if (sysctlbyname(Name.c_str(), nullptr, &CurBuffSize, nullptr, 0) == -1)
- return ValueUnion();
-
- ValueUnion buff(CurBuffSize);
- if (sysctlbyname(Name.c_str(), buff.data(), &buff.Size, nullptr, 0) == 0)
- return buff;
- return ValueUnion();
-#endif
-}
-
-BENCHMARK_MAYBE_UNUSED
-bool GetSysctl(std::string const& Name, std::string* Out) {
- Out->clear();
- auto Buff = GetSysctlImp(Name);
- if (!Buff) return false;
- Out->assign(Buff.data());
- return true;
-}
-
-template <class Tp,
- class = typename std::enable_if<std::is_integral<Tp>::value>::type>
-bool GetSysctl(std::string const& Name, Tp* Out) {
- *Out = 0;
- auto Buff = GetSysctlImp(Name);
- if (!Buff) return false;
- *Out = static_cast<Tp>(Buff.GetAsUnsigned());
- return true;
-}
-
-template <class Tp, size_t N>
-bool GetSysctl(std::string const& Name, std::array<Tp, N>* Out) {
- auto Buff = GetSysctlImp(Name);
- if (!Buff) return false;
- *Out = Buff.GetAsArray<Tp, N>();
- return true;
-}
-#endif
-
-template <class ArgT>
-bool ReadFromFile(std::string const& fname, ArgT* arg) {
- *arg = ArgT();
- std::ifstream f(fname.c_str());
- if (!f.is_open()) return false;
- f >> *arg;
- return f.good();
-}
-
-CPUInfo::Scaling CpuScaling(int num_cpus) {
- // We don't have a valid CPU count, so don't even bother.
- if (num_cpus <= 0) return CPUInfo::Scaling::UNKNOWN;
-#ifdef BENCHMARK_OS_QNX
- return CPUInfo::Scaling::UNKNOWN;
-#endif
-#ifndef BENCHMARK_OS_WINDOWS
- // On Linux, the CPUfreq subsystem exposes CPU information as files on the
- // local file system. If reading the exported files fails, then we may not be
- // running on Linux, so we silently ignore all the read errors.
- std::string res;
- for (int cpu = 0; cpu < num_cpus; ++cpu) {
- std::string governor_file =
- StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor");
- if (ReadFromFile(governor_file, &res) && res != "performance") return CPUInfo::Scaling::ENABLED;
- }
- return CPUInfo::Scaling::DISABLED;
-#endif
- return CPUInfo::Scaling::UNKNOWN;
-}
-
-int CountSetBitsInCPUMap(std::string Val) {
- auto CountBits = [](std::string Part) {
- using CPUMask = std::bitset<sizeof(std::uintptr_t) * CHAR_BIT>;
- Part = "0x" + Part;
- CPUMask Mask(benchmark::stoul(Part, nullptr, 16));
- return static_cast<int>(Mask.count());
- };
- size_t Pos;
- int total = 0;
- while ((Pos = Val.find(',')) != std::string::npos) {
- total += CountBits(Val.substr(0, Pos));
- Val = Val.substr(Pos + 1);
- }
- if (!Val.empty()) {
- total += CountBits(Val);
- }
- return total;
-}
-
-BENCHMARK_MAYBE_UNUSED
-std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() {
- std::vector<CPUInfo::CacheInfo> res;
- std::string dir = "/sys/devices/system/cpu/cpu0/cache/";
- int Idx = 0;
- while (true) {
- CPUInfo::CacheInfo info;
- std::string FPath = StrCat(dir, "index", Idx++, "/");
- std::ifstream f(StrCat(FPath, "size").c_str());
- if (!f.is_open()) break;
- std::string suffix;
- f >> info.size;
- if (f.fail())
- PrintErrorAndDie("Failed while reading file '", FPath, "size'");
- if (f.good()) {
- f >> suffix;
- if (f.bad())
- PrintErrorAndDie(
- "Invalid cache size format: failed to read size suffix");
- else if (f && suffix != "K")
- PrintErrorAndDie("Invalid cache size format: Expected bytes ", suffix);
- else if (suffix == "K")
- info.size *= 1024;
- }
- if (!ReadFromFile(StrCat(FPath, "type"), &info.type))
- PrintErrorAndDie("Failed to read from file ", FPath, "type");
- if (!ReadFromFile(StrCat(FPath, "level"), &info.level))
- PrintErrorAndDie("Failed to read from file ", FPath, "level");
- std::string map_str;
- if (!ReadFromFile(StrCat(FPath, "shared_cpu_map"), &map_str))
- PrintErrorAndDie("Failed to read from file ", FPath, "shared_cpu_map");
- info.num_sharing = CountSetBitsInCPUMap(map_str);
- res.push_back(info);
- }
-
- return res;
-}
-
-#ifdef BENCHMARK_OS_MACOSX
-std::vector<CPUInfo::CacheInfo> GetCacheSizesMacOSX() {
- std::vector<CPUInfo::CacheInfo> res;
- std::array<uint64_t, 4> CacheCounts{{0, 0, 0, 0}};
- GetSysctl("hw.cacheconfig", &CacheCounts);
-
- struct {
- std::string name;
- std::string type;
- int level;
- uint64_t num_sharing;
- } Cases[] = {{"hw.l1dcachesize", "Data", 1, CacheCounts[1]},
- {"hw.l1icachesize", "Instruction", 1, CacheCounts[1]},
- {"hw.l2cachesize", "Unified", 2, CacheCounts[2]},
- {"hw.l3cachesize", "Unified", 3, CacheCounts[3]}};
- for (auto& C : Cases) {
- int val;
- if (!GetSysctl(C.name, &val)) continue;
- CPUInfo::CacheInfo info;
- info.type = C.type;
- info.level = C.level;
- info.size = val;
- info.num_sharing = static_cast<int>(C.num_sharing);
- res.push_back(std::move(info));
- }
- return res;
-}
-#elif defined(BENCHMARK_OS_WINDOWS)
-std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() {
- std::vector<CPUInfo::CacheInfo> res;
- DWORD buffer_size = 0;
- using PInfo = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
- using CInfo = CACHE_DESCRIPTOR;
-
- using UPtr = std::unique_ptr<PInfo, decltype(&std::free)>;
- GetLogicalProcessorInformation(nullptr, &buffer_size);
- UPtr buff((PInfo*)malloc(buffer_size), &std::free);
- if (!GetLogicalProcessorInformation(buff.get(), &buffer_size))
- PrintErrorAndDie("Failed during call to GetLogicalProcessorInformation: ",
- GetLastError());
-
- PInfo* it = buff.get();
- PInfo* end = buff.get() + (buffer_size / sizeof(PInfo));
-
- for (; it != end; ++it) {
- if (it->Relationship != RelationCache) continue;
- using BitSet = std::bitset<sizeof(ULONG_PTR) * CHAR_BIT>;
- BitSet B(it->ProcessorMask);
- // To prevent duplicates, only consider caches where CPU 0 is specified
- if (!B.test(0)) continue;
- CInfo* Cache = &it->Cache;
- CPUInfo::CacheInfo C;
- C.num_sharing = static_cast<int>(B.count());
- C.level = Cache->Level;
- C.size = Cache->Size;
- switch (Cache->Type) {
- case CacheUnified:
- C.type = "Unified";
- break;
- case CacheInstruction:
- C.type = "Instruction";
- break;
- case CacheData:
- C.type = "Data";
- break;
- case CacheTrace:
- C.type = "Trace";
- break;
- default:
- C.type = "Unknown";
- break;
- }
- res.push_back(C);
- }
- return res;
-}
-#elif BENCHMARK_OS_QNX
-std::vector<CPUInfo::CacheInfo> GetCacheSizesQNX() {
- std::vector<CPUInfo::CacheInfo> res;
- struct cacheattr_entry *cache = SYSPAGE_ENTRY(cacheattr);
- uint32_t const elsize = SYSPAGE_ELEMENT_SIZE(cacheattr);
- int num = SYSPAGE_ENTRY_SIZE(cacheattr) / elsize ;
- for(int i = 0; i < num; ++i ) {
- CPUInfo::CacheInfo info;
- switch (cache->flags){
- case CACHE_FLAG_INSTR :
- info.type = "Instruction";
- info.level = 1;
- break;
- case CACHE_FLAG_DATA :
- info.type = "Data";
- info.level = 1;
- break;
- case CACHE_FLAG_UNIFIED :
- info.type = "Unified";
- info.level = 2;
- break;
- case CACHE_FLAG_SHARED :
- info.type = "Shared";
- info.level = 3;
- break;
- default :
- continue;
- break;
- }
- info.size = cache->line_size * cache->num_lines;
- info.num_sharing = 0;
- res.push_back(std::move(info));
- cache = SYSPAGE_ARRAY_ADJ_OFFSET(cacheattr, cache, elsize);
- }
- return res;
-}
-#endif
-
-std::vector<CPUInfo::CacheInfo> GetCacheSizes() {
-#ifdef BENCHMARK_OS_MACOSX
- return GetCacheSizesMacOSX();
-#elif defined(BENCHMARK_OS_WINDOWS)
- return GetCacheSizesWindows();
-#elif defined(BENCHMARK_OS_QNX)
- return GetCacheSizesQNX();
-#else
- return GetCacheSizesFromKVFS();
-#endif
-}
-
-std::string GetSystemName() {
-#if defined(BENCHMARK_OS_WINDOWS)
- std::string str;
- const unsigned COUNT = MAX_COMPUTERNAME_LENGTH+1;
- TCHAR hostname[COUNT] = {'\0'};
- DWORD DWCOUNT = COUNT;
- if (!GetComputerName(hostname, &DWCOUNT))
- return std::string("");
-#ifndef UNICODE
- str = std::string(hostname, DWCOUNT);
-#else
- //Using wstring_convert, Is deprecated in C++17
- using convert_type = std::codecvt_utf8<wchar_t>;
- std::wstring_convert<convert_type, wchar_t> converter;
- std::wstring wStr(hostname, DWCOUNT);
- str = converter.to_bytes(wStr);
-#endif
- return str;
-#else // defined(BENCHMARK_OS_WINDOWS)
-#ifndef HOST_NAME_MAX
-#ifdef BENCHMARK_HAS_SYSCTL // BSD/Mac Doesnt have HOST_NAME_MAX defined
-#define HOST_NAME_MAX 64
-#elif defined(BENCHMARK_OS_NACL)
-#define HOST_NAME_MAX 64
-#elif defined(BENCHMARK_OS_QNX)
-#define HOST_NAME_MAX 154
-#elif defined(BENCHMARK_OS_RTEMS)
-#define HOST_NAME_MAX 256
-#else
-#warning "HOST_NAME_MAX not defined. using 64"
-#define HOST_NAME_MAX 64
-#endif
-#endif // def HOST_NAME_MAX
- char hostname[HOST_NAME_MAX];
- int retVal = gethostname(hostname, HOST_NAME_MAX);
- if (retVal != 0) return std::string("");
- return std::string(hostname);
-#endif // Catch-all POSIX block.
-}
-
-int GetNumCPUs() {
-#ifdef BENCHMARK_HAS_SYSCTL
- int NumCPU = -1;
- if (GetSysctl("hw.ncpu", &NumCPU)) return NumCPU;
- fprintf(stderr, "Err: %s\n", strerror(errno));
- std::exit(EXIT_FAILURE);
-#elif defined(BENCHMARK_OS_WINDOWS)
- SYSTEM_INFO sysinfo;
- // Use memset as opposed to = {} to avoid GCC missing initializer false
- // positives.
- std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
- GetSystemInfo(&sysinfo);
- return sysinfo.dwNumberOfProcessors; // number of logical
- // processors in the current
- // group
-#elif defined(BENCHMARK_OS_SOLARIS)
- // Returns -1 in case of a failure.
- int NumCPU = sysconf(_SC_NPROCESSORS_ONLN);
- if (NumCPU < 0) {
- fprintf(stderr,
- "sysconf(_SC_NPROCESSORS_ONLN) failed with error: %s\n",
- strerror(errno));
- }
- return NumCPU;
-#elif defined(BENCHMARK_OS_QNX)
- return static_cast<int>(_syspage_ptr->num_cpu);
-#else
- int NumCPUs = 0;
- int MaxID = -1;
- std::ifstream f("/proc/cpuinfo");
- if (!f.is_open()) {
- std::cerr << "failed to open /proc/cpuinfo\n";
- return -1;
- }
- const std::string Key = "processor";
- std::string ln;
- while (std::getline(f, ln)) {
- if (ln.empty()) continue;
- size_t SplitIdx = ln.find(':');
- std::string value;
-#if defined(__s390__)
- // s390 has another format in /proc/cpuinfo
- // it needs to be parsed differently
- if (SplitIdx != std::string::npos) value = ln.substr(Key.size()+1,SplitIdx-Key.size()-1);
-#else
- if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1);
-#endif
- if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) {
- NumCPUs++;
- if (!value.empty()) {
- int CurID = benchmark::stoi(value);
- MaxID = std::max(CurID, MaxID);
- }
- }
- }
- if (f.bad()) {
- std::cerr << "Failure reading /proc/cpuinfo\n";
- return -1;
- }
- if (!f.eof()) {
- std::cerr << "Failed to read to end of /proc/cpuinfo\n";
- return -1;
- }
- f.close();
-
- if ((MaxID + 1) != NumCPUs) {
- fprintf(stderr,
- "CPU ID assignments in /proc/cpuinfo seem messed up."
- " This is usually caused by a bad BIOS.\n");
- }
- return NumCPUs;
-#endif
- BENCHMARK_UNREACHABLE();
-}
-
-double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) {
- // Currently, scaling is only used on linux path here,
- // suppress diagnostics about it being unused on other paths.
- (void)scaling;
-
-#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
- long freq;
-
- // If the kernel is exporting the tsc frequency use that. There are issues
- // where cpuinfo_max_freq cannot be relied on because the BIOS may be
- // exporintg an invalid p-state (on x86) or p-states may be used to put the
- // processor in a new mode (turbo mode). Essentially, those frequencies
- // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
- // well.
- if (ReadFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)
- // If CPU scaling is disabled, use the the *current* frequency.
- // Note that we specifically don't want to read cpuinfo_cur_freq,
- // because it is only readable by root.
- || (scaling == CPUInfo::Scaling::DISABLED &&
- ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq",
- &freq))
- // Otherwise, if CPU scaling may be in effect, we want to use
- // the *maximum* frequency, not whatever CPU speed some random processor
- // happens to be using now.
- || ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
- &freq)) {
- // The value is in kHz (as the file name suggests). For example, on a
- // 2GHz warpstation, the file contains the value "2000000".
- return freq * 1000.0;
- }
-
- const double error_value = -1;
- double bogo_clock = error_value;
-
- std::ifstream f("/proc/cpuinfo");
- if (!f.is_open()) {
- std::cerr << "failed to open /proc/cpuinfo\n";
- return error_value;
- }
-
- auto startsWithKey = [](std::string const& Value, std::string const& Key) {
- if (Key.size() > Value.size()) return false;
- auto Cmp = [&](char X, char Y) {
- return std::tolower(X) == std::tolower(Y);
- };
- return std::equal(Key.begin(), Key.end(), Value.begin(), Cmp);
- };
-
- std::string ln;
- while (std::getline(f, ln)) {
- if (ln.empty()) continue;
- size_t SplitIdx = ln.find(':');
- std::string value;
- if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1);
- // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
- // accept positive values. Some environments (virtual machines) report zero,
- // which would cause infinite looping in WallTime_Init.
- if (startsWithKey(ln, "cpu MHz")) {
- if (!value.empty()) {
- double cycles_per_second = benchmark::stod(value) * 1000000.0;
- if (cycles_per_second > 0) return cycles_per_second;
- }
- } else if (startsWithKey(ln, "bogomips")) {
- if (!value.empty()) {
- bogo_clock = benchmark::stod(value) * 1000000.0;
- if (bogo_clock < 0.0) bogo_clock = error_value;
- }
- }
- }
- if (f.bad()) {
- std::cerr << "Failure reading /proc/cpuinfo\n";
- return error_value;
- }
- if (!f.eof()) {
- std::cerr << "Failed to read to end of /proc/cpuinfo\n";
- return error_value;
- }
- f.close();
- // If we found the bogomips clock, but nothing better, we'll use it (but
- // we're not happy about it); otherwise, fallback to the rough estimation
- // below.
- if (bogo_clock >= 0.0) return bogo_clock;
-
-#elif defined BENCHMARK_HAS_SYSCTL
- constexpr auto* FreqStr =
-#if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD)
- "machdep.tsc_freq";
-#elif defined BENCHMARK_OS_OPENBSD
- "hw.cpuspeed";
-#elif defined BENCHMARK_OS_DRAGONFLY
- "hw.tsc_frequency";
-#else
- "hw.cpufrequency";
-#endif
- unsigned long long hz = 0;
-#if defined BENCHMARK_OS_OPENBSD
- if (GetSysctl(FreqStr, &hz)) return hz * 1000000;
-#else
- if (GetSysctl(FreqStr, &hz)) return hz;
-#endif
- fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
- FreqStr, strerror(errno));
-
-#elif defined BENCHMARK_OS_WINDOWS
- // In NT, read MHz from the registry. If we fail to do so or we're in win9x
- // then make a crude estimate.
- DWORD data, data_size = sizeof(data);
- if (IsWindowsXPOrGreater() &&
- SUCCEEDED(
- SHGetValueA(HKEY_LOCAL_MACHINE,
- "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
- "~MHz", nullptr, &data, &data_size)))
- return static_cast<double>((int64_t)data *
- (int64_t)(1000 * 1000)); // was mhz
-#elif defined (BENCHMARK_OS_SOLARIS)
- kstat_ctl_t *kc = kstat_open();
- if (!kc) {
- std::cerr << "failed to open /dev/kstat\n";
- return -1;
- }
- kstat_t *ksp = kstat_lookup(kc, (char*)"cpu_info", -1, (char*)"cpu_info0");
- if (!ksp) {
- std::cerr << "failed to lookup in /dev/kstat\n";
- return -1;
- }
- if (kstat_read(kc, ksp, NULL) < 0) {
- std::cerr << "failed to read from /dev/kstat\n";
- return -1;
- }
- kstat_named_t *knp =
- (kstat_named_t*)kstat_data_lookup(ksp, (char*)"current_clock_Hz");
- if (!knp) {
- std::cerr << "failed to lookup data in /dev/kstat\n";
- return -1;
- }
- if (knp->data_type != KSTAT_DATA_UINT64) {
- std::cerr << "current_clock_Hz is of unexpected data type: "
- << knp->data_type << "\n";
- return -1;
- }
- double clock_hz = knp->value.ui64;
- kstat_close(kc);
- return clock_hz;
-#elif defined (BENCHMARK_OS_QNX)
- return static_cast<double>((int64_t)(SYSPAGE_ENTRY(cpuinfo)->speed) *
- (int64_t)(1000 * 1000));
-#endif
- // If we've fallen through, attempt to roughly estimate the CPU clock rate.
- const int estimate_time_ms = 1000;
- const auto start_ticks = cycleclock::Now();
- SleepForMilliseconds(estimate_time_ms);
- return static_cast<double>(cycleclock::Now() - start_ticks);
-}
-
-std::vector<double> GetLoadAvg() {
-#if (defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \
- defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \
- defined BENCHMARK_OS_OPENBSD || defined BENCHMARK_OS_DRAGONFLY) && \
- !defined(__ANDROID__)
- constexpr int kMaxSamples = 3;
- std::vector<double> res(kMaxSamples, 0.0);
- const int nelem = getloadavg(res.data(), kMaxSamples);
- if (nelem < 1) {
- res.clear();
- } else {
- res.resize(nelem);
- }
- return res;
-#else
- return {};
-#endif
-}
-
-} // end namespace
-
-const CPUInfo& CPUInfo::Get() {
- static const CPUInfo* info = new CPUInfo();
- return *info;
-}
-
-CPUInfo::CPUInfo()
- : num_cpus(GetNumCPUs()),
- scaling(CpuScaling(num_cpus)),
- cycles_per_second(GetCPUCyclesPerSecond(scaling)),
- caches(GetCacheSizes()),
- load_avg(GetLoadAvg()) {}
-
-const SystemInfo& SystemInfo::Get() {
- static const SystemInfo* info = new SystemInfo();
- return *info;
-}
-
-SystemInfo::SystemInfo() : name(GetSystemName()) {}
-} // end namespace benchmark