1*dbb99499SAndroid Build Coastguard Worker // Copyright 2015 Google Inc. All rights reserved.
2*dbb99499SAndroid Build Coastguard Worker //
3*dbb99499SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*dbb99499SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*dbb99499SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*dbb99499SAndroid Build Coastguard Worker //
7*dbb99499SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*dbb99499SAndroid Build Coastguard Worker //
9*dbb99499SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*dbb99499SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*dbb99499SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*dbb99499SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*dbb99499SAndroid Build Coastguard Worker // limitations under the License.
14*dbb99499SAndroid Build Coastguard Worker
15*dbb99499SAndroid Build Coastguard Worker #include "internal_macros.h"
16*dbb99499SAndroid Build Coastguard Worker
17*dbb99499SAndroid Build Coastguard Worker #ifdef BENCHMARK_OS_WINDOWS
18*dbb99499SAndroid Build Coastguard Worker #if !defined(WINVER) || WINVER < 0x0600
19*dbb99499SAndroid Build Coastguard Worker #undef WINVER
20*dbb99499SAndroid Build Coastguard Worker #define WINVER 0x0600
21*dbb99499SAndroid Build Coastguard Worker #endif // WINVER handling
22*dbb99499SAndroid Build Coastguard Worker #include <shlwapi.h>
23*dbb99499SAndroid Build Coastguard Worker #undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
24*dbb99499SAndroid Build Coastguard Worker #include <versionhelpers.h>
25*dbb99499SAndroid Build Coastguard Worker #include <windows.h>
26*dbb99499SAndroid Build Coastguard Worker
27*dbb99499SAndroid Build Coastguard Worker #include <codecvt>
28*dbb99499SAndroid Build Coastguard Worker #else
29*dbb99499SAndroid Build Coastguard Worker #include <fcntl.h>
30*dbb99499SAndroid Build Coastguard Worker #if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
31*dbb99499SAndroid Build Coastguard Worker #include <sys/resource.h>
32*dbb99499SAndroid Build Coastguard Worker #endif
33*dbb99499SAndroid Build Coastguard Worker #include <sys/time.h>
34*dbb99499SAndroid Build Coastguard Worker #include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
35*dbb99499SAndroid Build Coastguard Worker #include <unistd.h>
36*dbb99499SAndroid Build Coastguard Worker #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \
37*dbb99499SAndroid Build Coastguard Worker defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD || \
38*dbb99499SAndroid Build Coastguard Worker defined BENCHMARK_OS_DRAGONFLY
39*dbb99499SAndroid Build Coastguard Worker #define BENCHMARK_HAS_SYSCTL
40*dbb99499SAndroid Build Coastguard Worker #include <sys/sysctl.h>
41*dbb99499SAndroid Build Coastguard Worker #endif
42*dbb99499SAndroid Build Coastguard Worker #endif
43*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_OS_SOLARIS)
44*dbb99499SAndroid Build Coastguard Worker #include <kstat.h>
45*dbb99499SAndroid Build Coastguard Worker #include <netdb.h>
46*dbb99499SAndroid Build Coastguard Worker #endif
47*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_OS_QNX)
48*dbb99499SAndroid Build Coastguard Worker #include <sys/syspage.h>
49*dbb99499SAndroid Build Coastguard Worker #endif
50*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_OS_QURT)
51*dbb99499SAndroid Build Coastguard Worker #include <qurt.h>
52*dbb99499SAndroid Build Coastguard Worker #endif
53*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
54*dbb99499SAndroid Build Coastguard Worker #include <pthread.h>
55*dbb99499SAndroid Build Coastguard Worker #endif
56*dbb99499SAndroid Build Coastguard Worker
57*dbb99499SAndroid Build Coastguard Worker #include <algorithm>
58*dbb99499SAndroid Build Coastguard Worker #include <array>
59*dbb99499SAndroid Build Coastguard Worker #include <bitset>
60*dbb99499SAndroid Build Coastguard Worker #include <cerrno>
61*dbb99499SAndroid Build Coastguard Worker #include <climits>
62*dbb99499SAndroid Build Coastguard Worker #include <cstdint>
63*dbb99499SAndroid Build Coastguard Worker #include <cstdio>
64*dbb99499SAndroid Build Coastguard Worker #include <cstdlib>
65*dbb99499SAndroid Build Coastguard Worker #include <cstring>
66*dbb99499SAndroid Build Coastguard Worker #include <fstream>
67*dbb99499SAndroid Build Coastguard Worker #include <iostream>
68*dbb99499SAndroid Build Coastguard Worker #include <iterator>
69*dbb99499SAndroid Build Coastguard Worker #include <limits>
70*dbb99499SAndroid Build Coastguard Worker #include <locale>
71*dbb99499SAndroid Build Coastguard Worker #include <memory>
72*dbb99499SAndroid Build Coastguard Worker #include <random>
73*dbb99499SAndroid Build Coastguard Worker #include <sstream>
74*dbb99499SAndroid Build Coastguard Worker #include <utility>
75*dbb99499SAndroid Build Coastguard Worker
76*dbb99499SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
77*dbb99499SAndroid Build Coastguard Worker #include "check.h"
78*dbb99499SAndroid Build Coastguard Worker #include "cycleclock.h"
79*dbb99499SAndroid Build Coastguard Worker #include "internal_macros.h"
80*dbb99499SAndroid Build Coastguard Worker #include "log.h"
81*dbb99499SAndroid Build Coastguard Worker #include "string_util.h"
82*dbb99499SAndroid Build Coastguard Worker #include "timers.h"
83*dbb99499SAndroid Build Coastguard Worker
84*dbb99499SAndroid Build Coastguard Worker namespace benchmark {
85*dbb99499SAndroid Build Coastguard Worker namespace {
86*dbb99499SAndroid Build Coastguard Worker
PrintImp(std::ostream & out)87*dbb99499SAndroid Build Coastguard Worker void PrintImp(std::ostream& out) { out << std::endl; }
88*dbb99499SAndroid Build Coastguard Worker
89*dbb99499SAndroid Build Coastguard Worker template <class First, class... Rest>
PrintImp(std::ostream & out,First && f,Rest &&...rest)90*dbb99499SAndroid Build Coastguard Worker void PrintImp(std::ostream& out, First&& f, Rest&&... rest) {
91*dbb99499SAndroid Build Coastguard Worker out << std::forward<First>(f);
92*dbb99499SAndroid Build Coastguard Worker PrintImp(out, std::forward<Rest>(rest)...);
93*dbb99499SAndroid Build Coastguard Worker }
94*dbb99499SAndroid Build Coastguard Worker
95*dbb99499SAndroid Build Coastguard Worker template <class... Args>
PrintErrorAndDie(Args &&...args)96*dbb99499SAndroid Build Coastguard Worker BENCHMARK_NORETURN void PrintErrorAndDie(Args&&... args) {
97*dbb99499SAndroid Build Coastguard Worker PrintImp(std::cerr, std::forward<Args>(args)...);
98*dbb99499SAndroid Build Coastguard Worker std::exit(EXIT_FAILURE);
99*dbb99499SAndroid Build Coastguard Worker }
100*dbb99499SAndroid Build Coastguard Worker
101*dbb99499SAndroid Build Coastguard Worker #ifdef BENCHMARK_HAS_SYSCTL
102*dbb99499SAndroid Build Coastguard Worker
103*dbb99499SAndroid Build Coastguard Worker /// ValueUnion - A type used to correctly alias the byte-for-byte output of
104*dbb99499SAndroid Build Coastguard Worker /// `sysctl` with the result type it's to be interpreted as.
105*dbb99499SAndroid Build Coastguard Worker struct ValueUnion {
106*dbb99499SAndroid Build Coastguard Worker union DataT {
107*dbb99499SAndroid Build Coastguard Worker int32_t int32_value;
108*dbb99499SAndroid Build Coastguard Worker int64_t int64_value;
109*dbb99499SAndroid Build Coastguard Worker // For correct aliasing of union members from bytes.
110*dbb99499SAndroid Build Coastguard Worker char bytes[8];
111*dbb99499SAndroid Build Coastguard Worker };
112*dbb99499SAndroid Build Coastguard Worker using DataPtr = std::unique_ptr<DataT, decltype(&std::free)>;
113*dbb99499SAndroid Build Coastguard Worker
114*dbb99499SAndroid Build Coastguard Worker // The size of the data union member + its trailing array size.
115*dbb99499SAndroid Build Coastguard Worker std::size_t size;
116*dbb99499SAndroid Build Coastguard Worker DataPtr buff;
117*dbb99499SAndroid Build Coastguard Worker
118*dbb99499SAndroid Build Coastguard Worker public:
ValueUnionbenchmark::__anonf672d7010111::ValueUnion119*dbb99499SAndroid Build Coastguard Worker ValueUnion() : size(0), buff(nullptr, &std::free) {}
120*dbb99499SAndroid Build Coastguard Worker
ValueUnionbenchmark::__anonf672d7010111::ValueUnion121*dbb99499SAndroid Build Coastguard Worker explicit ValueUnion(std::size_t buff_size)
122*dbb99499SAndroid Build Coastguard Worker : size(sizeof(DataT) + buff_size),
123*dbb99499SAndroid Build Coastguard Worker buff(::new (std::malloc(size)) DataT(), &std::free) {}
124*dbb99499SAndroid Build Coastguard Worker
125*dbb99499SAndroid Build Coastguard Worker ValueUnion(ValueUnion&& other) = default;
126*dbb99499SAndroid Build Coastguard Worker
operator boolbenchmark::__anonf672d7010111::ValueUnion127*dbb99499SAndroid Build Coastguard Worker explicit operator bool() const { return bool(buff); }
128*dbb99499SAndroid Build Coastguard Worker
databenchmark::__anonf672d7010111::ValueUnion129*dbb99499SAndroid Build Coastguard Worker char* data() const { return buff->bytes; }
130*dbb99499SAndroid Build Coastguard Worker
GetAsStringbenchmark::__anonf672d7010111::ValueUnion131*dbb99499SAndroid Build Coastguard Worker std::string GetAsString() const { return std::string(data()); }
132*dbb99499SAndroid Build Coastguard Worker
GetAsIntegerbenchmark::__anonf672d7010111::ValueUnion133*dbb99499SAndroid Build Coastguard Worker int64_t GetAsInteger() const {
134*dbb99499SAndroid Build Coastguard Worker if (size == sizeof(buff->int32_value))
135*dbb99499SAndroid Build Coastguard Worker return buff->int32_value;
136*dbb99499SAndroid Build Coastguard Worker else if (size == sizeof(buff->int64_value))
137*dbb99499SAndroid Build Coastguard Worker return buff->int64_value;
138*dbb99499SAndroid Build Coastguard Worker BENCHMARK_UNREACHABLE();
139*dbb99499SAndroid Build Coastguard Worker }
140*dbb99499SAndroid Build Coastguard Worker
141*dbb99499SAndroid Build Coastguard Worker template <class T, int N>
GetAsArraybenchmark::__anonf672d7010111::ValueUnion142*dbb99499SAndroid Build Coastguard Worker std::array<T, N> GetAsArray() {
143*dbb99499SAndroid Build Coastguard Worker const int arr_size = sizeof(T) * N;
144*dbb99499SAndroid Build Coastguard Worker BM_CHECK_LE(arr_size, size);
145*dbb99499SAndroid Build Coastguard Worker std::array<T, N> arr;
146*dbb99499SAndroid Build Coastguard Worker std::memcpy(arr.data(), data(), arr_size);
147*dbb99499SAndroid Build Coastguard Worker return arr;
148*dbb99499SAndroid Build Coastguard Worker }
149*dbb99499SAndroid Build Coastguard Worker };
150*dbb99499SAndroid Build Coastguard Worker
GetSysctlImp(std::string const & name)151*dbb99499SAndroid Build Coastguard Worker ValueUnion GetSysctlImp(std::string const& name) {
152*dbb99499SAndroid Build Coastguard Worker #if defined BENCHMARK_OS_OPENBSD
153*dbb99499SAndroid Build Coastguard Worker int mib[2];
154*dbb99499SAndroid Build Coastguard Worker
155*dbb99499SAndroid Build Coastguard Worker mib[0] = CTL_HW;
156*dbb99499SAndroid Build Coastguard Worker if ((name == "hw.ncpu") || (name == "hw.cpuspeed")) {
157*dbb99499SAndroid Build Coastguard Worker ValueUnion buff(sizeof(int));
158*dbb99499SAndroid Build Coastguard Worker
159*dbb99499SAndroid Build Coastguard Worker if (name == "hw.ncpu") {
160*dbb99499SAndroid Build Coastguard Worker mib[1] = HW_NCPU;
161*dbb99499SAndroid Build Coastguard Worker } else {
162*dbb99499SAndroid Build Coastguard Worker mib[1] = HW_CPUSPEED;
163*dbb99499SAndroid Build Coastguard Worker }
164*dbb99499SAndroid Build Coastguard Worker
165*dbb99499SAndroid Build Coastguard Worker if (sysctl(mib, 2, buff.data(), &buff.size, nullptr, 0) == -1) {
166*dbb99499SAndroid Build Coastguard Worker return ValueUnion();
167*dbb99499SAndroid Build Coastguard Worker }
168*dbb99499SAndroid Build Coastguard Worker return buff;
169*dbb99499SAndroid Build Coastguard Worker }
170*dbb99499SAndroid Build Coastguard Worker return ValueUnion();
171*dbb99499SAndroid Build Coastguard Worker #else
172*dbb99499SAndroid Build Coastguard Worker std::size_t cur_buff_size = 0;
173*dbb99499SAndroid Build Coastguard Worker if (sysctlbyname(name.c_str(), nullptr, &cur_buff_size, nullptr, 0) == -1)
174*dbb99499SAndroid Build Coastguard Worker return ValueUnion();
175*dbb99499SAndroid Build Coastguard Worker
176*dbb99499SAndroid Build Coastguard Worker ValueUnion buff(cur_buff_size);
177*dbb99499SAndroid Build Coastguard Worker if (sysctlbyname(name.c_str(), buff.data(), &buff.size, nullptr, 0) == 0)
178*dbb99499SAndroid Build Coastguard Worker return buff;
179*dbb99499SAndroid Build Coastguard Worker return ValueUnion();
180*dbb99499SAndroid Build Coastguard Worker #endif
181*dbb99499SAndroid Build Coastguard Worker }
182*dbb99499SAndroid Build Coastguard Worker
183*dbb99499SAndroid Build Coastguard Worker BENCHMARK_MAYBE_UNUSED
GetSysctl(std::string const & name,std::string * out)184*dbb99499SAndroid Build Coastguard Worker bool GetSysctl(std::string const& name, std::string* out) {
185*dbb99499SAndroid Build Coastguard Worker out->clear();
186*dbb99499SAndroid Build Coastguard Worker auto buff = GetSysctlImp(name);
187*dbb99499SAndroid Build Coastguard Worker if (!buff) return false;
188*dbb99499SAndroid Build Coastguard Worker out->assign(buff.data());
189*dbb99499SAndroid Build Coastguard Worker return true;
190*dbb99499SAndroid Build Coastguard Worker }
191*dbb99499SAndroid Build Coastguard Worker
192*dbb99499SAndroid Build Coastguard Worker template <class Tp,
193*dbb99499SAndroid Build Coastguard Worker class = typename std::enable_if<std::is_integral<Tp>::value>::type>
GetSysctl(std::string const & name,Tp * out)194*dbb99499SAndroid Build Coastguard Worker bool GetSysctl(std::string const& name, Tp* out) {
195*dbb99499SAndroid Build Coastguard Worker *out = 0;
196*dbb99499SAndroid Build Coastguard Worker auto buff = GetSysctlImp(name);
197*dbb99499SAndroid Build Coastguard Worker if (!buff) return false;
198*dbb99499SAndroid Build Coastguard Worker *out = static_cast<Tp>(buff.GetAsInteger());
199*dbb99499SAndroid Build Coastguard Worker return true;
200*dbb99499SAndroid Build Coastguard Worker }
201*dbb99499SAndroid Build Coastguard Worker
202*dbb99499SAndroid Build Coastguard Worker template <class Tp, size_t N>
GetSysctl(std::string const & name,std::array<Tp,N> * out)203*dbb99499SAndroid Build Coastguard Worker bool GetSysctl(std::string const& name, std::array<Tp, N>* out) {
204*dbb99499SAndroid Build Coastguard Worker auto buff = GetSysctlImp(name);
205*dbb99499SAndroid Build Coastguard Worker if (!buff) return false;
206*dbb99499SAndroid Build Coastguard Worker *out = buff.GetAsArray<Tp, N>();
207*dbb99499SAndroid Build Coastguard Worker return true;
208*dbb99499SAndroid Build Coastguard Worker }
209*dbb99499SAndroid Build Coastguard Worker #endif
210*dbb99499SAndroid Build Coastguard Worker
211*dbb99499SAndroid Build Coastguard Worker template <class ArgT>
ReadFromFile(std::string const & fname,ArgT * arg)212*dbb99499SAndroid Build Coastguard Worker bool ReadFromFile(std::string const& fname, ArgT* arg) {
213*dbb99499SAndroid Build Coastguard Worker *arg = ArgT();
214*dbb99499SAndroid Build Coastguard Worker std::ifstream f(fname.c_str());
215*dbb99499SAndroid Build Coastguard Worker if (!f.is_open()) return false;
216*dbb99499SAndroid Build Coastguard Worker f >> *arg;
217*dbb99499SAndroid Build Coastguard Worker return f.good();
218*dbb99499SAndroid Build Coastguard Worker }
219*dbb99499SAndroid Build Coastguard Worker
CpuScaling(int num_cpus)220*dbb99499SAndroid Build Coastguard Worker CPUInfo::Scaling CpuScaling(int num_cpus) {
221*dbb99499SAndroid Build Coastguard Worker // We don't have a valid CPU count, so don't even bother.
222*dbb99499SAndroid Build Coastguard Worker if (num_cpus <= 0) return CPUInfo::Scaling::UNKNOWN;
223*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_OS_QNX)
224*dbb99499SAndroid Build Coastguard Worker return CPUInfo::Scaling::UNKNOWN;
225*dbb99499SAndroid Build Coastguard Worker #elif !defined(BENCHMARK_OS_WINDOWS)
226*dbb99499SAndroid Build Coastguard Worker // On Linux, the CPUfreq subsystem exposes CPU information as files on the
227*dbb99499SAndroid Build Coastguard Worker // local file system. If reading the exported files fails, then we may not be
228*dbb99499SAndroid Build Coastguard Worker // running on Linux, so we silently ignore all the read errors.
229*dbb99499SAndroid Build Coastguard Worker std::string res;
230*dbb99499SAndroid Build Coastguard Worker for (int cpu = 0; cpu < num_cpus; ++cpu) {
231*dbb99499SAndroid Build Coastguard Worker std::string governor_file =
232*dbb99499SAndroid Build Coastguard Worker StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor");
233*dbb99499SAndroid Build Coastguard Worker if (ReadFromFile(governor_file, &res) && res != "performance")
234*dbb99499SAndroid Build Coastguard Worker return CPUInfo::Scaling::ENABLED;
235*dbb99499SAndroid Build Coastguard Worker }
236*dbb99499SAndroid Build Coastguard Worker return CPUInfo::Scaling::DISABLED;
237*dbb99499SAndroid Build Coastguard Worker #else
238*dbb99499SAndroid Build Coastguard Worker return CPUInfo::Scaling::UNKNOWN;
239*dbb99499SAndroid Build Coastguard Worker #endif
240*dbb99499SAndroid Build Coastguard Worker }
241*dbb99499SAndroid Build Coastguard Worker
CountSetBitsInCPUMap(std::string val)242*dbb99499SAndroid Build Coastguard Worker int CountSetBitsInCPUMap(std::string val) {
243*dbb99499SAndroid Build Coastguard Worker auto CountBits = [](std::string part) {
244*dbb99499SAndroid Build Coastguard Worker using CPUMask = std::bitset<sizeof(std::uintptr_t) * CHAR_BIT>;
245*dbb99499SAndroid Build Coastguard Worker part = "0x" + part;
246*dbb99499SAndroid Build Coastguard Worker CPUMask mask(benchmark::stoul(part, nullptr, 16));
247*dbb99499SAndroid Build Coastguard Worker return static_cast<int>(mask.count());
248*dbb99499SAndroid Build Coastguard Worker };
249*dbb99499SAndroid Build Coastguard Worker std::size_t pos;
250*dbb99499SAndroid Build Coastguard Worker int total = 0;
251*dbb99499SAndroid Build Coastguard Worker while ((pos = val.find(',')) != std::string::npos) {
252*dbb99499SAndroid Build Coastguard Worker total += CountBits(val.substr(0, pos));
253*dbb99499SAndroid Build Coastguard Worker val = val.substr(pos + 1);
254*dbb99499SAndroid Build Coastguard Worker }
255*dbb99499SAndroid Build Coastguard Worker if (!val.empty()) {
256*dbb99499SAndroid Build Coastguard Worker total += CountBits(val);
257*dbb99499SAndroid Build Coastguard Worker }
258*dbb99499SAndroid Build Coastguard Worker return total;
259*dbb99499SAndroid Build Coastguard Worker }
260*dbb99499SAndroid Build Coastguard Worker
261*dbb99499SAndroid Build Coastguard Worker BENCHMARK_MAYBE_UNUSED
GetCacheSizesFromKVFS()262*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() {
263*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> res;
264*dbb99499SAndroid Build Coastguard Worker std::string dir = "/sys/devices/system/cpu/cpu0/cache/";
265*dbb99499SAndroid Build Coastguard Worker int idx = 0;
266*dbb99499SAndroid Build Coastguard Worker while (true) {
267*dbb99499SAndroid Build Coastguard Worker CPUInfo::CacheInfo info;
268*dbb99499SAndroid Build Coastguard Worker std::string fpath = StrCat(dir, "index", idx++, "/");
269*dbb99499SAndroid Build Coastguard Worker std::ifstream f(StrCat(fpath, "size").c_str());
270*dbb99499SAndroid Build Coastguard Worker if (!f.is_open()) break;
271*dbb99499SAndroid Build Coastguard Worker std::string suffix;
272*dbb99499SAndroid Build Coastguard Worker f >> info.size;
273*dbb99499SAndroid Build Coastguard Worker if (f.fail())
274*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed while reading file '", fpath, "size'");
275*dbb99499SAndroid Build Coastguard Worker if (f.good()) {
276*dbb99499SAndroid Build Coastguard Worker f >> suffix;
277*dbb99499SAndroid Build Coastguard Worker if (f.bad())
278*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie(
279*dbb99499SAndroid Build Coastguard Worker "Invalid cache size format: failed to read size suffix");
280*dbb99499SAndroid Build Coastguard Worker else if (f && suffix != "K")
281*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Invalid cache size format: Expected bytes ", suffix);
282*dbb99499SAndroid Build Coastguard Worker else if (suffix == "K")
283*dbb99499SAndroid Build Coastguard Worker info.size *= 1024;
284*dbb99499SAndroid Build Coastguard Worker }
285*dbb99499SAndroid Build Coastguard Worker if (!ReadFromFile(StrCat(fpath, "type"), &info.type))
286*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed to read from file ", fpath, "type");
287*dbb99499SAndroid Build Coastguard Worker if (!ReadFromFile(StrCat(fpath, "level"), &info.level))
288*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed to read from file ", fpath, "level");
289*dbb99499SAndroid Build Coastguard Worker std::string map_str;
290*dbb99499SAndroid Build Coastguard Worker if (!ReadFromFile(StrCat(fpath, "shared_cpu_map"), &map_str))
291*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed to read from file ", fpath, "shared_cpu_map");
292*dbb99499SAndroid Build Coastguard Worker info.num_sharing = CountSetBitsInCPUMap(map_str);
293*dbb99499SAndroid Build Coastguard Worker res.push_back(info);
294*dbb99499SAndroid Build Coastguard Worker }
295*dbb99499SAndroid Build Coastguard Worker
296*dbb99499SAndroid Build Coastguard Worker return res;
297*dbb99499SAndroid Build Coastguard Worker }
298*dbb99499SAndroid Build Coastguard Worker
299*dbb99499SAndroid Build Coastguard Worker #ifdef BENCHMARK_OS_MACOSX
GetCacheSizesMacOSX()300*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> GetCacheSizesMacOSX() {
301*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> res;
302*dbb99499SAndroid Build Coastguard Worker std::array<int, 4> cache_counts{{0, 0, 0, 0}};
303*dbb99499SAndroid Build Coastguard Worker GetSysctl("hw.cacheconfig", &cache_counts);
304*dbb99499SAndroid Build Coastguard Worker
305*dbb99499SAndroid Build Coastguard Worker struct {
306*dbb99499SAndroid Build Coastguard Worker std::string name;
307*dbb99499SAndroid Build Coastguard Worker std::string type;
308*dbb99499SAndroid Build Coastguard Worker int level;
309*dbb99499SAndroid Build Coastguard Worker int num_sharing;
310*dbb99499SAndroid Build Coastguard Worker } cases[] = {{"hw.l1dcachesize", "Data", 1, cache_counts[1]},
311*dbb99499SAndroid Build Coastguard Worker {"hw.l1icachesize", "Instruction", 1, cache_counts[1]},
312*dbb99499SAndroid Build Coastguard Worker {"hw.l2cachesize", "Unified", 2, cache_counts[2]},
313*dbb99499SAndroid Build Coastguard Worker {"hw.l3cachesize", "Unified", 3, cache_counts[3]}};
314*dbb99499SAndroid Build Coastguard Worker for (auto& c : cases) {
315*dbb99499SAndroid Build Coastguard Worker int val;
316*dbb99499SAndroid Build Coastguard Worker if (!GetSysctl(c.name, &val)) continue;
317*dbb99499SAndroid Build Coastguard Worker CPUInfo::CacheInfo info;
318*dbb99499SAndroid Build Coastguard Worker info.type = c.type;
319*dbb99499SAndroid Build Coastguard Worker info.level = c.level;
320*dbb99499SAndroid Build Coastguard Worker info.size = val;
321*dbb99499SAndroid Build Coastguard Worker info.num_sharing = c.num_sharing;
322*dbb99499SAndroid Build Coastguard Worker res.push_back(std::move(info));
323*dbb99499SAndroid Build Coastguard Worker }
324*dbb99499SAndroid Build Coastguard Worker return res;
325*dbb99499SAndroid Build Coastguard Worker }
326*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_WINDOWS)
GetCacheSizesWindows()327*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() {
328*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> res;
329*dbb99499SAndroid Build Coastguard Worker DWORD buffer_size = 0;
330*dbb99499SAndroid Build Coastguard Worker using PInfo = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
331*dbb99499SAndroid Build Coastguard Worker using CInfo = CACHE_DESCRIPTOR;
332*dbb99499SAndroid Build Coastguard Worker
333*dbb99499SAndroid Build Coastguard Worker using UPtr = std::unique_ptr<PInfo, decltype(&std::free)>;
334*dbb99499SAndroid Build Coastguard Worker GetLogicalProcessorInformation(nullptr, &buffer_size);
335*dbb99499SAndroid Build Coastguard Worker UPtr buff(static_cast<PInfo*>(std::malloc(buffer_size)), &std::free);
336*dbb99499SAndroid Build Coastguard Worker if (!GetLogicalProcessorInformation(buff.get(), &buffer_size))
337*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed during call to GetLogicalProcessorInformation: ",
338*dbb99499SAndroid Build Coastguard Worker GetLastError());
339*dbb99499SAndroid Build Coastguard Worker
340*dbb99499SAndroid Build Coastguard Worker PInfo* it = buff.get();
341*dbb99499SAndroid Build Coastguard Worker PInfo* end = buff.get() + (buffer_size / sizeof(PInfo));
342*dbb99499SAndroid Build Coastguard Worker
343*dbb99499SAndroid Build Coastguard Worker for (; it != end; ++it) {
344*dbb99499SAndroid Build Coastguard Worker if (it->Relationship != RelationCache) continue;
345*dbb99499SAndroid Build Coastguard Worker using BitSet = std::bitset<sizeof(ULONG_PTR) * CHAR_BIT>;
346*dbb99499SAndroid Build Coastguard Worker BitSet b(it->ProcessorMask);
347*dbb99499SAndroid Build Coastguard Worker // To prevent duplicates, only consider caches where CPU 0 is specified
348*dbb99499SAndroid Build Coastguard Worker if (!b.test(0)) continue;
349*dbb99499SAndroid Build Coastguard Worker const CInfo& cache = it->Cache;
350*dbb99499SAndroid Build Coastguard Worker CPUInfo::CacheInfo C;
351*dbb99499SAndroid Build Coastguard Worker C.num_sharing = static_cast<int>(b.count());
352*dbb99499SAndroid Build Coastguard Worker C.level = cache.Level;
353*dbb99499SAndroid Build Coastguard Worker C.size = static_cast<int>(cache.Size);
354*dbb99499SAndroid Build Coastguard Worker C.type = "Unknown";
355*dbb99499SAndroid Build Coastguard Worker switch (cache.Type) {
356*dbb99499SAndroid Build Coastguard Worker case CacheUnified:
357*dbb99499SAndroid Build Coastguard Worker C.type = "Unified";
358*dbb99499SAndroid Build Coastguard Worker break;
359*dbb99499SAndroid Build Coastguard Worker case CacheInstruction:
360*dbb99499SAndroid Build Coastguard Worker C.type = "Instruction";
361*dbb99499SAndroid Build Coastguard Worker break;
362*dbb99499SAndroid Build Coastguard Worker case CacheData:
363*dbb99499SAndroid Build Coastguard Worker C.type = "Data";
364*dbb99499SAndroid Build Coastguard Worker break;
365*dbb99499SAndroid Build Coastguard Worker case CacheTrace:
366*dbb99499SAndroid Build Coastguard Worker C.type = "Trace";
367*dbb99499SAndroid Build Coastguard Worker break;
368*dbb99499SAndroid Build Coastguard Worker }
369*dbb99499SAndroid Build Coastguard Worker res.push_back(C);
370*dbb99499SAndroid Build Coastguard Worker }
371*dbb99499SAndroid Build Coastguard Worker return res;
372*dbb99499SAndroid Build Coastguard Worker }
373*dbb99499SAndroid Build Coastguard Worker #elif BENCHMARK_OS_QNX
GetCacheSizesQNX()374*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> GetCacheSizesQNX() {
375*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> res;
376*dbb99499SAndroid Build Coastguard Worker struct cacheattr_entry* cache = SYSPAGE_ENTRY(cacheattr);
377*dbb99499SAndroid Build Coastguard Worker uint32_t const elsize = SYSPAGE_ELEMENT_SIZE(cacheattr);
378*dbb99499SAndroid Build Coastguard Worker int num = SYSPAGE_ENTRY_SIZE(cacheattr) / elsize;
379*dbb99499SAndroid Build Coastguard Worker for (int i = 0; i < num; ++i) {
380*dbb99499SAndroid Build Coastguard Worker CPUInfo::CacheInfo info;
381*dbb99499SAndroid Build Coastguard Worker switch (cache->flags) {
382*dbb99499SAndroid Build Coastguard Worker case CACHE_FLAG_INSTR:
383*dbb99499SAndroid Build Coastguard Worker info.type = "Instruction";
384*dbb99499SAndroid Build Coastguard Worker info.level = 1;
385*dbb99499SAndroid Build Coastguard Worker break;
386*dbb99499SAndroid Build Coastguard Worker case CACHE_FLAG_DATA:
387*dbb99499SAndroid Build Coastguard Worker info.type = "Data";
388*dbb99499SAndroid Build Coastguard Worker info.level = 1;
389*dbb99499SAndroid Build Coastguard Worker break;
390*dbb99499SAndroid Build Coastguard Worker case CACHE_FLAG_UNIFIED:
391*dbb99499SAndroid Build Coastguard Worker info.type = "Unified";
392*dbb99499SAndroid Build Coastguard Worker info.level = 2;
393*dbb99499SAndroid Build Coastguard Worker break;
394*dbb99499SAndroid Build Coastguard Worker case CACHE_FLAG_SHARED:
395*dbb99499SAndroid Build Coastguard Worker info.type = "Shared";
396*dbb99499SAndroid Build Coastguard Worker info.level = 3;
397*dbb99499SAndroid Build Coastguard Worker break;
398*dbb99499SAndroid Build Coastguard Worker default:
399*dbb99499SAndroid Build Coastguard Worker continue;
400*dbb99499SAndroid Build Coastguard Worker break;
401*dbb99499SAndroid Build Coastguard Worker }
402*dbb99499SAndroid Build Coastguard Worker info.size = cache->line_size * cache->num_lines;
403*dbb99499SAndroid Build Coastguard Worker info.num_sharing = 0;
404*dbb99499SAndroid Build Coastguard Worker res.push_back(std::move(info));
405*dbb99499SAndroid Build Coastguard Worker cache = SYSPAGE_ARRAY_ADJ_OFFSET(cacheattr, cache, elsize);
406*dbb99499SAndroid Build Coastguard Worker }
407*dbb99499SAndroid Build Coastguard Worker return res;
408*dbb99499SAndroid Build Coastguard Worker }
409*dbb99499SAndroid Build Coastguard Worker #endif
410*dbb99499SAndroid Build Coastguard Worker
GetCacheSizes()411*dbb99499SAndroid Build Coastguard Worker std::vector<CPUInfo::CacheInfo> GetCacheSizes() {
412*dbb99499SAndroid Build Coastguard Worker #ifdef BENCHMARK_OS_MACOSX
413*dbb99499SAndroid Build Coastguard Worker return GetCacheSizesMacOSX();
414*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_WINDOWS)
415*dbb99499SAndroid Build Coastguard Worker return GetCacheSizesWindows();
416*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QNX)
417*dbb99499SAndroid Build Coastguard Worker return GetCacheSizesQNX();
418*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QURT)
419*dbb99499SAndroid Build Coastguard Worker return std::vector<CPUInfo::CacheInfo>();
420*dbb99499SAndroid Build Coastguard Worker #else
421*dbb99499SAndroid Build Coastguard Worker return GetCacheSizesFromKVFS();
422*dbb99499SAndroid Build Coastguard Worker #endif
423*dbb99499SAndroid Build Coastguard Worker }
424*dbb99499SAndroid Build Coastguard Worker
GetSystemName()425*dbb99499SAndroid Build Coastguard Worker std::string GetSystemName() {
426*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_OS_WINDOWS)
427*dbb99499SAndroid Build Coastguard Worker std::string str;
428*dbb99499SAndroid Build Coastguard Worker static constexpr int COUNT = MAX_COMPUTERNAME_LENGTH + 1;
429*dbb99499SAndroid Build Coastguard Worker TCHAR hostname[COUNT] = {'\0'};
430*dbb99499SAndroid Build Coastguard Worker DWORD DWCOUNT = COUNT;
431*dbb99499SAndroid Build Coastguard Worker if (!GetComputerName(hostname, &DWCOUNT)) return std::string("");
432*dbb99499SAndroid Build Coastguard Worker #ifndef UNICODE
433*dbb99499SAndroid Build Coastguard Worker str = std::string(hostname, DWCOUNT);
434*dbb99499SAndroid Build Coastguard Worker #else
435*dbb99499SAndroid Build Coastguard Worker // `WideCharToMultiByte` returns `0` when conversion fails.
436*dbb99499SAndroid Build Coastguard Worker int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname,
437*dbb99499SAndroid Build Coastguard Worker DWCOUNT, NULL, 0, NULL, NULL);
438*dbb99499SAndroid Build Coastguard Worker str.resize(len);
439*dbb99499SAndroid Build Coastguard Worker WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname, DWCOUNT, &str[0],
440*dbb99499SAndroid Build Coastguard Worker str.size(), NULL, NULL);
441*dbb99499SAndroid Build Coastguard Worker #endif
442*dbb99499SAndroid Build Coastguard Worker return str;
443*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QURT)
444*dbb99499SAndroid Build Coastguard Worker std::string str = "Hexagon DSP";
445*dbb99499SAndroid Build Coastguard Worker qurt_arch_version_t arch_version_struct;
446*dbb99499SAndroid Build Coastguard Worker if (qurt_sysenv_get_arch_version(&arch_version_struct) == QURT_EOK) {
447*dbb99499SAndroid Build Coastguard Worker str += " v";
448*dbb99499SAndroid Build Coastguard Worker str += std::to_string(arch_version_struct.arch_version);
449*dbb99499SAndroid Build Coastguard Worker }
450*dbb99499SAndroid Build Coastguard Worker return str;
451*dbb99499SAndroid Build Coastguard Worker #else
452*dbb99499SAndroid Build Coastguard Worker #ifndef HOST_NAME_MAX
453*dbb99499SAndroid Build Coastguard Worker #ifdef BENCHMARK_HAS_SYSCTL // BSD/Mac doesn't have HOST_NAME_MAX defined
454*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX 64
455*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_NACL)
456*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX 64
457*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QNX)
458*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX 154
459*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_RTEMS)
460*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX 256
461*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_SOLARIS)
462*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX MAXHOSTNAMELEN
463*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_ZOS)
464*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
465*dbb99499SAndroid Build Coastguard Worker #else
466*dbb99499SAndroid Build Coastguard Worker #pragma message("HOST_NAME_MAX not defined. using 64")
467*dbb99499SAndroid Build Coastguard Worker #define HOST_NAME_MAX 64
468*dbb99499SAndroid Build Coastguard Worker #endif
469*dbb99499SAndroid Build Coastguard Worker #endif // def HOST_NAME_MAX
470*dbb99499SAndroid Build Coastguard Worker char hostname[HOST_NAME_MAX];
471*dbb99499SAndroid Build Coastguard Worker int retVal = gethostname(hostname, HOST_NAME_MAX);
472*dbb99499SAndroid Build Coastguard Worker if (retVal != 0) return std::string("");
473*dbb99499SAndroid Build Coastguard Worker return std::string(hostname);
474*dbb99499SAndroid Build Coastguard Worker #endif // Catch-all POSIX block.
475*dbb99499SAndroid Build Coastguard Worker }
476*dbb99499SAndroid Build Coastguard Worker
GetNumCPUsImpl()477*dbb99499SAndroid Build Coastguard Worker int GetNumCPUsImpl() {
478*dbb99499SAndroid Build Coastguard Worker #ifdef BENCHMARK_HAS_SYSCTL
479*dbb99499SAndroid Build Coastguard Worker int num_cpu = -1;
480*dbb99499SAndroid Build Coastguard Worker if (GetSysctl("hw.ncpu", &num_cpu)) return num_cpu;
481*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Err: ", strerror(errno));
482*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_WINDOWS)
483*dbb99499SAndroid Build Coastguard Worker SYSTEM_INFO sysinfo;
484*dbb99499SAndroid Build Coastguard Worker // Use memset as opposed to = {} to avoid GCC missing initializer false
485*dbb99499SAndroid Build Coastguard Worker // positives.
486*dbb99499SAndroid Build Coastguard Worker std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
487*dbb99499SAndroid Build Coastguard Worker GetSystemInfo(&sysinfo);
488*dbb99499SAndroid Build Coastguard Worker // number of logical processors in the current group
489*dbb99499SAndroid Build Coastguard Worker return static_cast<int>(sysinfo.dwNumberOfProcessors);
490*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_SOLARIS)
491*dbb99499SAndroid Build Coastguard Worker // Returns -1 in case of a failure.
492*dbb99499SAndroid Build Coastguard Worker long num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
493*dbb99499SAndroid Build Coastguard Worker if (num_cpu < 0) {
494*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("sysconf(_SC_NPROCESSORS_ONLN) failed with error: ",
495*dbb99499SAndroid Build Coastguard Worker strerror(errno));
496*dbb99499SAndroid Build Coastguard Worker }
497*dbb99499SAndroid Build Coastguard Worker return (int)num_cpu;
498*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QNX)
499*dbb99499SAndroid Build Coastguard Worker return static_cast<int>(_syspage_ptr->num_cpu);
500*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QURT)
501*dbb99499SAndroid Build Coastguard Worker qurt_sysenv_max_hthreads_t hardware_threads;
502*dbb99499SAndroid Build Coastguard Worker if (qurt_sysenv_get_max_hw_threads(&hardware_threads) != QURT_EOK) {
503*dbb99499SAndroid Build Coastguard Worker hardware_threads.max_hthreads = 1;
504*dbb99499SAndroid Build Coastguard Worker }
505*dbb99499SAndroid Build Coastguard Worker return hardware_threads.max_hthreads;
506*dbb99499SAndroid Build Coastguard Worker #else
507*dbb99499SAndroid Build Coastguard Worker int num_cpus = 0;
508*dbb99499SAndroid Build Coastguard Worker int max_id = -1;
509*dbb99499SAndroid Build Coastguard Worker std::ifstream f("/proc/cpuinfo");
510*dbb99499SAndroid Build Coastguard Worker if (!f.is_open()) {
511*dbb99499SAndroid Build Coastguard Worker std::cerr << "Failed to open /proc/cpuinfo\n";
512*dbb99499SAndroid Build Coastguard Worker return -1;
513*dbb99499SAndroid Build Coastguard Worker }
514*dbb99499SAndroid Build Coastguard Worker #if defined(__alpha__)
515*dbb99499SAndroid Build Coastguard Worker const std::string Key = "cpus detected";
516*dbb99499SAndroid Build Coastguard Worker #else
517*dbb99499SAndroid Build Coastguard Worker const std::string Key = "processor";
518*dbb99499SAndroid Build Coastguard Worker #endif
519*dbb99499SAndroid Build Coastguard Worker std::string ln;
520*dbb99499SAndroid Build Coastguard Worker while (std::getline(f, ln)) {
521*dbb99499SAndroid Build Coastguard Worker if (ln.empty()) continue;
522*dbb99499SAndroid Build Coastguard Worker std::size_t split_idx = ln.find(':');
523*dbb99499SAndroid Build Coastguard Worker std::string value;
524*dbb99499SAndroid Build Coastguard Worker #if defined(__s390__)
525*dbb99499SAndroid Build Coastguard Worker // s390 has another format in /proc/cpuinfo
526*dbb99499SAndroid Build Coastguard Worker // it needs to be parsed differently
527*dbb99499SAndroid Build Coastguard Worker if (split_idx != std::string::npos)
528*dbb99499SAndroid Build Coastguard Worker value = ln.substr(Key.size() + 1, split_idx - Key.size() - 1);
529*dbb99499SAndroid Build Coastguard Worker #else
530*dbb99499SAndroid Build Coastguard Worker if (split_idx != std::string::npos) value = ln.substr(split_idx + 1);
531*dbb99499SAndroid Build Coastguard Worker #endif
532*dbb99499SAndroid Build Coastguard Worker if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) {
533*dbb99499SAndroid Build Coastguard Worker num_cpus++;
534*dbb99499SAndroid Build Coastguard Worker if (!value.empty()) {
535*dbb99499SAndroid Build Coastguard Worker const int cur_id = benchmark::stoi(value);
536*dbb99499SAndroid Build Coastguard Worker max_id = std::max(cur_id, max_id);
537*dbb99499SAndroid Build Coastguard Worker }
538*dbb99499SAndroid Build Coastguard Worker }
539*dbb99499SAndroid Build Coastguard Worker }
540*dbb99499SAndroid Build Coastguard Worker if (f.bad()) {
541*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failure reading /proc/cpuinfo");
542*dbb99499SAndroid Build Coastguard Worker }
543*dbb99499SAndroid Build Coastguard Worker if (!f.eof()) {
544*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed to read to end of /proc/cpuinfo");
545*dbb99499SAndroid Build Coastguard Worker }
546*dbb99499SAndroid Build Coastguard Worker f.close();
547*dbb99499SAndroid Build Coastguard Worker
548*dbb99499SAndroid Build Coastguard Worker if ((max_id + 1) != num_cpus) {
549*dbb99499SAndroid Build Coastguard Worker fprintf(stderr,
550*dbb99499SAndroid Build Coastguard Worker "CPU ID assignments in /proc/cpuinfo seem messed up."
551*dbb99499SAndroid Build Coastguard Worker " This is usually caused by a bad BIOS.\n");
552*dbb99499SAndroid Build Coastguard Worker }
553*dbb99499SAndroid Build Coastguard Worker return num_cpus;
554*dbb99499SAndroid Build Coastguard Worker #endif
555*dbb99499SAndroid Build Coastguard Worker BENCHMARK_UNREACHABLE();
556*dbb99499SAndroid Build Coastguard Worker }
557*dbb99499SAndroid Build Coastguard Worker
GetNumCPUs()558*dbb99499SAndroid Build Coastguard Worker int GetNumCPUs() {
559*dbb99499SAndroid Build Coastguard Worker const int num_cpus = GetNumCPUsImpl();
560*dbb99499SAndroid Build Coastguard Worker if (num_cpus < 1) {
561*dbb99499SAndroid Build Coastguard Worker std::cerr << "Unable to extract number of CPUs. If your platform uses "
562*dbb99499SAndroid Build Coastguard Worker "/proc/cpuinfo, custom support may need to be added.\n";
563*dbb99499SAndroid Build Coastguard Worker }
564*dbb99499SAndroid Build Coastguard Worker return num_cpus;
565*dbb99499SAndroid Build Coastguard Worker }
566*dbb99499SAndroid Build Coastguard Worker
567*dbb99499SAndroid Build Coastguard Worker class ThreadAffinityGuard final {
568*dbb99499SAndroid Build Coastguard Worker public:
ThreadAffinityGuard()569*dbb99499SAndroid Build Coastguard Worker ThreadAffinityGuard() : reset_affinity(SetAffinity()) {
570*dbb99499SAndroid Build Coastguard Worker if (!reset_affinity)
571*dbb99499SAndroid Build Coastguard Worker std::cerr << "***WARNING*** Failed to set thread affinity. Estimated CPU "
572*dbb99499SAndroid Build Coastguard Worker "frequency may be incorrect."
573*dbb99499SAndroid Build Coastguard Worker << std::endl;
574*dbb99499SAndroid Build Coastguard Worker }
575*dbb99499SAndroid Build Coastguard Worker
~ThreadAffinityGuard()576*dbb99499SAndroid Build Coastguard Worker ~ThreadAffinityGuard() {
577*dbb99499SAndroid Build Coastguard Worker if (!reset_affinity) return;
578*dbb99499SAndroid Build Coastguard Worker
579*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
580*dbb99499SAndroid Build Coastguard Worker int ret = pthread_setaffinity_np(self, sizeof(previous_affinity),
581*dbb99499SAndroid Build Coastguard Worker &previous_affinity);
582*dbb99499SAndroid Build Coastguard Worker if (ret == 0) return;
583*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_WINDOWS_WIN32)
584*dbb99499SAndroid Build Coastguard Worker DWORD_PTR ret = SetThreadAffinityMask(self, previous_affinity);
585*dbb99499SAndroid Build Coastguard Worker if (ret != 0) return;
586*dbb99499SAndroid Build Coastguard Worker #endif // def BENCHMARK_HAS_PTHREAD_AFFINITY
587*dbb99499SAndroid Build Coastguard Worker PrintErrorAndDie("Failed to reset thread affinity");
588*dbb99499SAndroid Build Coastguard Worker }
589*dbb99499SAndroid Build Coastguard Worker
590*dbb99499SAndroid Build Coastguard Worker ThreadAffinityGuard(ThreadAffinityGuard&&) = delete;
591*dbb99499SAndroid Build Coastguard Worker ThreadAffinityGuard(const ThreadAffinityGuard&) = delete;
592*dbb99499SAndroid Build Coastguard Worker ThreadAffinityGuard& operator=(ThreadAffinityGuard&&) = delete;
593*dbb99499SAndroid Build Coastguard Worker ThreadAffinityGuard& operator=(const ThreadAffinityGuard&) = delete;
594*dbb99499SAndroid Build Coastguard Worker
595*dbb99499SAndroid Build Coastguard Worker private:
SetAffinity()596*dbb99499SAndroid Build Coastguard Worker bool SetAffinity() {
597*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
598*dbb99499SAndroid Build Coastguard Worker int ret;
599*dbb99499SAndroid Build Coastguard Worker self = pthread_self();
600*dbb99499SAndroid Build Coastguard Worker ret = pthread_getaffinity_np(self, sizeof(previous_affinity),
601*dbb99499SAndroid Build Coastguard Worker &previous_affinity);
602*dbb99499SAndroid Build Coastguard Worker if (ret != 0) return false;
603*dbb99499SAndroid Build Coastguard Worker
604*dbb99499SAndroid Build Coastguard Worker cpu_set_t affinity;
605*dbb99499SAndroid Build Coastguard Worker memcpy(&affinity, &previous_affinity, sizeof(affinity));
606*dbb99499SAndroid Build Coastguard Worker
607*dbb99499SAndroid Build Coastguard Worker bool is_first_cpu = true;
608*dbb99499SAndroid Build Coastguard Worker
609*dbb99499SAndroid Build Coastguard Worker for (int i = 0; i < CPU_SETSIZE; ++i)
610*dbb99499SAndroid Build Coastguard Worker if (CPU_ISSET(i, &affinity)) {
611*dbb99499SAndroid Build Coastguard Worker if (is_first_cpu)
612*dbb99499SAndroid Build Coastguard Worker is_first_cpu = false;
613*dbb99499SAndroid Build Coastguard Worker else
614*dbb99499SAndroid Build Coastguard Worker CPU_CLR(i, &affinity);
615*dbb99499SAndroid Build Coastguard Worker }
616*dbb99499SAndroid Build Coastguard Worker
617*dbb99499SAndroid Build Coastguard Worker if (is_first_cpu) return false;
618*dbb99499SAndroid Build Coastguard Worker
619*dbb99499SAndroid Build Coastguard Worker ret = pthread_setaffinity_np(self, sizeof(affinity), &affinity);
620*dbb99499SAndroid Build Coastguard Worker return ret == 0;
621*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_WINDOWS_WIN32)
622*dbb99499SAndroid Build Coastguard Worker self = GetCurrentThread();
623*dbb99499SAndroid Build Coastguard Worker DWORD_PTR mask = static_cast<DWORD_PTR>(1) << GetCurrentProcessorNumber();
624*dbb99499SAndroid Build Coastguard Worker previous_affinity = SetThreadAffinityMask(self, mask);
625*dbb99499SAndroid Build Coastguard Worker return previous_affinity != 0;
626*dbb99499SAndroid Build Coastguard Worker #else
627*dbb99499SAndroid Build Coastguard Worker return false;
628*dbb99499SAndroid Build Coastguard Worker #endif // def BENCHMARK_HAS_PTHREAD_AFFINITY
629*dbb99499SAndroid Build Coastguard Worker }
630*dbb99499SAndroid Build Coastguard Worker
631*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
632*dbb99499SAndroid Build Coastguard Worker pthread_t self;
633*dbb99499SAndroid Build Coastguard Worker cpu_set_t previous_affinity;
634*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_WINDOWS_WIN32)
635*dbb99499SAndroid Build Coastguard Worker HANDLE self;
636*dbb99499SAndroid Build Coastguard Worker DWORD_PTR previous_affinity;
637*dbb99499SAndroid Build Coastguard Worker #endif // def BENCHMARK_HAS_PTHREAD_AFFINITY
638*dbb99499SAndroid Build Coastguard Worker bool reset_affinity;
639*dbb99499SAndroid Build Coastguard Worker };
640*dbb99499SAndroid Build Coastguard Worker
GetCPUCyclesPerSecond(CPUInfo::Scaling scaling)641*dbb99499SAndroid Build Coastguard Worker double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) {
642*dbb99499SAndroid Build Coastguard Worker // Currently, scaling is only used on linux path here,
643*dbb99499SAndroid Build Coastguard Worker // suppress diagnostics about it being unused on other paths.
644*dbb99499SAndroid Build Coastguard Worker (void)scaling;
645*dbb99499SAndroid Build Coastguard Worker
646*dbb99499SAndroid Build Coastguard Worker #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
647*dbb99499SAndroid Build Coastguard Worker long freq;
648*dbb99499SAndroid Build Coastguard Worker
649*dbb99499SAndroid Build Coastguard Worker // If the kernel is exporting the tsc frequency use that. There are issues
650*dbb99499SAndroid Build Coastguard Worker // where cpuinfo_max_freq cannot be relied on because the BIOS may be
651*dbb99499SAndroid Build Coastguard Worker // exporintg an invalid p-state (on x86) or p-states may be used to put the
652*dbb99499SAndroid Build Coastguard Worker // processor in a new mode (turbo mode). Essentially, those frequencies
653*dbb99499SAndroid Build Coastguard Worker // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
654*dbb99499SAndroid Build Coastguard Worker // well.
655*dbb99499SAndroid Build Coastguard Worker if (ReadFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)
656*dbb99499SAndroid Build Coastguard Worker // If CPU scaling is disabled, use the *current* frequency.
657*dbb99499SAndroid Build Coastguard Worker // Note that we specifically don't want to read cpuinfo_cur_freq,
658*dbb99499SAndroid Build Coastguard Worker // because it is only readable by root.
659*dbb99499SAndroid Build Coastguard Worker || (scaling == CPUInfo::Scaling::DISABLED &&
660*dbb99499SAndroid Build Coastguard Worker ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq",
661*dbb99499SAndroid Build Coastguard Worker &freq))
662*dbb99499SAndroid Build Coastguard Worker // Otherwise, if CPU scaling may be in effect, we want to use
663*dbb99499SAndroid Build Coastguard Worker // the *maximum* frequency, not whatever CPU speed some random processor
664*dbb99499SAndroid Build Coastguard Worker // happens to be using now.
665*dbb99499SAndroid Build Coastguard Worker || ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
666*dbb99499SAndroid Build Coastguard Worker &freq)) {
667*dbb99499SAndroid Build Coastguard Worker // The value is in kHz (as the file name suggests). For example, on a
668*dbb99499SAndroid Build Coastguard Worker // 2GHz warpstation, the file contains the value "2000000".
669*dbb99499SAndroid Build Coastguard Worker return static_cast<double>(freq) * 1000.0;
670*dbb99499SAndroid Build Coastguard Worker }
671*dbb99499SAndroid Build Coastguard Worker
672*dbb99499SAndroid Build Coastguard Worker const double error_value = -1;
673*dbb99499SAndroid Build Coastguard Worker double bogo_clock = error_value;
674*dbb99499SAndroid Build Coastguard Worker
675*dbb99499SAndroid Build Coastguard Worker std::ifstream f("/proc/cpuinfo");
676*dbb99499SAndroid Build Coastguard Worker if (!f.is_open()) {
677*dbb99499SAndroid Build Coastguard Worker std::cerr << "failed to open /proc/cpuinfo\n";
678*dbb99499SAndroid Build Coastguard Worker return error_value;
679*dbb99499SAndroid Build Coastguard Worker }
680*dbb99499SAndroid Build Coastguard Worker
681*dbb99499SAndroid Build Coastguard Worker auto StartsWithKey = [](std::string const& Value, std::string const& Key) {
682*dbb99499SAndroid Build Coastguard Worker if (Key.size() > Value.size()) return false;
683*dbb99499SAndroid Build Coastguard Worker auto Cmp = [&](char X, char Y) {
684*dbb99499SAndroid Build Coastguard Worker return std::tolower(X) == std::tolower(Y);
685*dbb99499SAndroid Build Coastguard Worker };
686*dbb99499SAndroid Build Coastguard Worker return std::equal(Key.begin(), Key.end(), Value.begin(), Cmp);
687*dbb99499SAndroid Build Coastguard Worker };
688*dbb99499SAndroid Build Coastguard Worker
689*dbb99499SAndroid Build Coastguard Worker std::string ln;
690*dbb99499SAndroid Build Coastguard Worker while (std::getline(f, ln)) {
691*dbb99499SAndroid Build Coastguard Worker if (ln.empty()) continue;
692*dbb99499SAndroid Build Coastguard Worker std::size_t split_idx = ln.find(':');
693*dbb99499SAndroid Build Coastguard Worker std::string value;
694*dbb99499SAndroid Build Coastguard Worker if (split_idx != std::string::npos) value = ln.substr(split_idx + 1);
695*dbb99499SAndroid Build Coastguard Worker // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
696*dbb99499SAndroid Build Coastguard Worker // accept positive values. Some environments (virtual machines) report zero,
697*dbb99499SAndroid Build Coastguard Worker // which would cause infinite looping in WallTime_Init.
698*dbb99499SAndroid Build Coastguard Worker if (StartsWithKey(ln, "cpu MHz")) {
699*dbb99499SAndroid Build Coastguard Worker if (!value.empty()) {
700*dbb99499SAndroid Build Coastguard Worker double cycles_per_second = benchmark::stod(value) * 1000000.0;
701*dbb99499SAndroid Build Coastguard Worker if (cycles_per_second > 0) return cycles_per_second;
702*dbb99499SAndroid Build Coastguard Worker }
703*dbb99499SAndroid Build Coastguard Worker } else if (StartsWithKey(ln, "bogomips")) {
704*dbb99499SAndroid Build Coastguard Worker if (!value.empty()) {
705*dbb99499SAndroid Build Coastguard Worker bogo_clock = benchmark::stod(value) * 1000000.0;
706*dbb99499SAndroid Build Coastguard Worker if (bogo_clock < 0.0) bogo_clock = error_value;
707*dbb99499SAndroid Build Coastguard Worker }
708*dbb99499SAndroid Build Coastguard Worker }
709*dbb99499SAndroid Build Coastguard Worker }
710*dbb99499SAndroid Build Coastguard Worker if (f.bad()) {
711*dbb99499SAndroid Build Coastguard Worker std::cerr << "Failure reading /proc/cpuinfo\n";
712*dbb99499SAndroid Build Coastguard Worker return error_value;
713*dbb99499SAndroid Build Coastguard Worker }
714*dbb99499SAndroid Build Coastguard Worker if (!f.eof()) {
715*dbb99499SAndroid Build Coastguard Worker std::cerr << "Failed to read to end of /proc/cpuinfo\n";
716*dbb99499SAndroid Build Coastguard Worker return error_value;
717*dbb99499SAndroid Build Coastguard Worker }
718*dbb99499SAndroid Build Coastguard Worker f.close();
719*dbb99499SAndroid Build Coastguard Worker // If we found the bogomips clock, but nothing better, we'll use it (but
720*dbb99499SAndroid Build Coastguard Worker // we're not happy about it); otherwise, fallback to the rough estimation
721*dbb99499SAndroid Build Coastguard Worker // below.
722*dbb99499SAndroid Build Coastguard Worker if (bogo_clock >= 0.0) return bogo_clock;
723*dbb99499SAndroid Build Coastguard Worker
724*dbb99499SAndroid Build Coastguard Worker #elif defined BENCHMARK_HAS_SYSCTL
725*dbb99499SAndroid Build Coastguard Worker constexpr auto* freqStr =
726*dbb99499SAndroid Build Coastguard Worker #if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD)
727*dbb99499SAndroid Build Coastguard Worker "machdep.tsc_freq";
728*dbb99499SAndroid Build Coastguard Worker #elif defined BENCHMARK_OS_OPENBSD
729*dbb99499SAndroid Build Coastguard Worker "hw.cpuspeed";
730*dbb99499SAndroid Build Coastguard Worker #elif defined BENCHMARK_OS_DRAGONFLY
731*dbb99499SAndroid Build Coastguard Worker "hw.tsc_frequency";
732*dbb99499SAndroid Build Coastguard Worker #else
733*dbb99499SAndroid Build Coastguard Worker "hw.cpufrequency";
734*dbb99499SAndroid Build Coastguard Worker #endif
735*dbb99499SAndroid Build Coastguard Worker unsigned long long hz = 0;
736*dbb99499SAndroid Build Coastguard Worker #if defined BENCHMARK_OS_OPENBSD
737*dbb99499SAndroid Build Coastguard Worker if (GetSysctl(freqStr, &hz)) return static_cast<double>(hz * 1000000);
738*dbb99499SAndroid Build Coastguard Worker #else
739*dbb99499SAndroid Build Coastguard Worker if (GetSysctl(freqStr, &hz)) return static_cast<double>(hz);
740*dbb99499SAndroid Build Coastguard Worker #endif
741*dbb99499SAndroid Build Coastguard Worker fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
742*dbb99499SAndroid Build Coastguard Worker freqStr, strerror(errno));
743*dbb99499SAndroid Build Coastguard Worker fprintf(stderr,
744*dbb99499SAndroid Build Coastguard Worker "This does not affect benchmark measurements, only the "
745*dbb99499SAndroid Build Coastguard Worker "metadata output.\n");
746*dbb99499SAndroid Build Coastguard Worker
747*dbb99499SAndroid Build Coastguard Worker #elif defined BENCHMARK_OS_WINDOWS_WIN32
748*dbb99499SAndroid Build Coastguard Worker // In NT, read MHz from the registry. If we fail to do so or we're in win9x
749*dbb99499SAndroid Build Coastguard Worker // then make a crude estimate.
750*dbb99499SAndroid Build Coastguard Worker DWORD data, data_size = sizeof(data);
751*dbb99499SAndroid Build Coastguard Worker if (IsWindowsXPOrGreater() &&
752*dbb99499SAndroid Build Coastguard Worker SUCCEEDED(
753*dbb99499SAndroid Build Coastguard Worker SHGetValueA(HKEY_LOCAL_MACHINE,
754*dbb99499SAndroid Build Coastguard Worker "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
755*dbb99499SAndroid Build Coastguard Worker "~MHz", nullptr, &data, &data_size)))
756*dbb99499SAndroid Build Coastguard Worker return static_cast<double>(static_cast<int64_t>(data) *
757*dbb99499SAndroid Build Coastguard Worker static_cast<int64_t>(1000 * 1000)); // was mhz
758*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_SOLARIS)
759*dbb99499SAndroid Build Coastguard Worker kstat_ctl_t* kc = kstat_open();
760*dbb99499SAndroid Build Coastguard Worker if (!kc) {
761*dbb99499SAndroid Build Coastguard Worker std::cerr << "failed to open /dev/kstat\n";
762*dbb99499SAndroid Build Coastguard Worker return -1;
763*dbb99499SAndroid Build Coastguard Worker }
764*dbb99499SAndroid Build Coastguard Worker kstat_t* ksp = kstat_lookup(kc, const_cast<char*>("cpu_info"), -1,
765*dbb99499SAndroid Build Coastguard Worker const_cast<char*>("cpu_info0"));
766*dbb99499SAndroid Build Coastguard Worker if (!ksp) {
767*dbb99499SAndroid Build Coastguard Worker std::cerr << "failed to lookup in /dev/kstat\n";
768*dbb99499SAndroid Build Coastguard Worker return -1;
769*dbb99499SAndroid Build Coastguard Worker }
770*dbb99499SAndroid Build Coastguard Worker if (kstat_read(kc, ksp, NULL) < 0) {
771*dbb99499SAndroid Build Coastguard Worker std::cerr << "failed to read from /dev/kstat\n";
772*dbb99499SAndroid Build Coastguard Worker return -1;
773*dbb99499SAndroid Build Coastguard Worker }
774*dbb99499SAndroid Build Coastguard Worker kstat_named_t* knp = (kstat_named_t*)kstat_data_lookup(
775*dbb99499SAndroid Build Coastguard Worker ksp, const_cast<char*>("current_clock_Hz"));
776*dbb99499SAndroid Build Coastguard Worker if (!knp) {
777*dbb99499SAndroid Build Coastguard Worker std::cerr << "failed to lookup data in /dev/kstat\n";
778*dbb99499SAndroid Build Coastguard Worker return -1;
779*dbb99499SAndroid Build Coastguard Worker }
780*dbb99499SAndroid Build Coastguard Worker if (knp->data_type != KSTAT_DATA_UINT64) {
781*dbb99499SAndroid Build Coastguard Worker std::cerr << "current_clock_Hz is of unexpected data type: "
782*dbb99499SAndroid Build Coastguard Worker << knp->data_type << "\n";
783*dbb99499SAndroid Build Coastguard Worker return -1;
784*dbb99499SAndroid Build Coastguard Worker }
785*dbb99499SAndroid Build Coastguard Worker double clock_hz = knp->value.ui64;
786*dbb99499SAndroid Build Coastguard Worker kstat_close(kc);
787*dbb99499SAndroid Build Coastguard Worker return clock_hz;
788*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QNX)
789*dbb99499SAndroid Build Coastguard Worker return static_cast<double>(
790*dbb99499SAndroid Build Coastguard Worker static_cast<int64_t>(SYSPAGE_ENTRY(cpuinfo)->speed) *
791*dbb99499SAndroid Build Coastguard Worker static_cast<int64_t>(1000 * 1000));
792*dbb99499SAndroid Build Coastguard Worker #elif defined(BENCHMARK_OS_QURT)
793*dbb99499SAndroid Build Coastguard Worker // QuRT doesn't provide any API to query Hexagon frequency.
794*dbb99499SAndroid Build Coastguard Worker return 1000000000;
795*dbb99499SAndroid Build Coastguard Worker #endif
796*dbb99499SAndroid Build Coastguard Worker // If we've fallen through, attempt to roughly estimate the CPU clock rate.
797*dbb99499SAndroid Build Coastguard Worker
798*dbb99499SAndroid Build Coastguard Worker // Make sure to use the same cycle counter when starting and stopping the
799*dbb99499SAndroid Build Coastguard Worker // cycle timer. We just pin the current thread to a cpu in the previous
800*dbb99499SAndroid Build Coastguard Worker // affinity set.
801*dbb99499SAndroid Build Coastguard Worker ThreadAffinityGuard affinity_guard;
802*dbb99499SAndroid Build Coastguard Worker
803*dbb99499SAndroid Build Coastguard Worker static constexpr double estimate_time_s = 1.0;
804*dbb99499SAndroid Build Coastguard Worker const double start_time = ChronoClockNow();
805*dbb99499SAndroid Build Coastguard Worker const auto start_ticks = cycleclock::Now();
806*dbb99499SAndroid Build Coastguard Worker
807*dbb99499SAndroid Build Coastguard Worker // Impose load instead of calling sleep() to make sure the cycle counter
808*dbb99499SAndroid Build Coastguard Worker // works.
809*dbb99499SAndroid Build Coastguard Worker using PRNG = std::minstd_rand;
810*dbb99499SAndroid Build Coastguard Worker using Result = PRNG::result_type;
811*dbb99499SAndroid Build Coastguard Worker PRNG rng(static_cast<Result>(start_ticks));
812*dbb99499SAndroid Build Coastguard Worker
813*dbb99499SAndroid Build Coastguard Worker Result state = 0;
814*dbb99499SAndroid Build Coastguard Worker
815*dbb99499SAndroid Build Coastguard Worker do {
816*dbb99499SAndroid Build Coastguard Worker static constexpr size_t batch_size = 10000;
817*dbb99499SAndroid Build Coastguard Worker rng.discard(batch_size);
818*dbb99499SAndroid Build Coastguard Worker state += rng();
819*dbb99499SAndroid Build Coastguard Worker
820*dbb99499SAndroid Build Coastguard Worker } while (ChronoClockNow() - start_time < estimate_time_s);
821*dbb99499SAndroid Build Coastguard Worker
822*dbb99499SAndroid Build Coastguard Worker DoNotOptimize(state);
823*dbb99499SAndroid Build Coastguard Worker
824*dbb99499SAndroid Build Coastguard Worker const auto end_ticks = cycleclock::Now();
825*dbb99499SAndroid Build Coastguard Worker const double end_time = ChronoClockNow();
826*dbb99499SAndroid Build Coastguard Worker
827*dbb99499SAndroid Build Coastguard Worker return static_cast<double>(end_ticks - start_ticks) / (end_time - start_time);
828*dbb99499SAndroid Build Coastguard Worker // Reset the affinity of current thread when the lifetime of affinity_guard
829*dbb99499SAndroid Build Coastguard Worker // ends.
830*dbb99499SAndroid Build Coastguard Worker }
831*dbb99499SAndroid Build Coastguard Worker
GetLoadAvg()832*dbb99499SAndroid Build Coastguard Worker std::vector<double> GetLoadAvg() {
833*dbb99499SAndroid Build Coastguard Worker #if (defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \
834*dbb99499SAndroid Build Coastguard Worker defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \
835*dbb99499SAndroid Build Coastguard Worker defined BENCHMARK_OS_OPENBSD || defined BENCHMARK_OS_DRAGONFLY) && \
836*dbb99499SAndroid Build Coastguard Worker !(defined(__ANDROID__) && __ANDROID_API__ < 29)
837*dbb99499SAndroid Build Coastguard Worker static constexpr int kMaxSamples = 3;
838*dbb99499SAndroid Build Coastguard Worker std::vector<double> res(kMaxSamples, 0.0);
839*dbb99499SAndroid Build Coastguard Worker const size_t nelem = static_cast<size_t>(getloadavg(res.data(), kMaxSamples));
840*dbb99499SAndroid Build Coastguard Worker if (nelem < 1) {
841*dbb99499SAndroid Build Coastguard Worker res.clear();
842*dbb99499SAndroid Build Coastguard Worker } else {
843*dbb99499SAndroid Build Coastguard Worker res.resize(nelem);
844*dbb99499SAndroid Build Coastguard Worker }
845*dbb99499SAndroid Build Coastguard Worker return res;
846*dbb99499SAndroid Build Coastguard Worker #else
847*dbb99499SAndroid Build Coastguard Worker return {};
848*dbb99499SAndroid Build Coastguard Worker #endif
849*dbb99499SAndroid Build Coastguard Worker }
850*dbb99499SAndroid Build Coastguard Worker
851*dbb99499SAndroid Build Coastguard Worker } // end namespace
852*dbb99499SAndroid Build Coastguard Worker
Get()853*dbb99499SAndroid Build Coastguard Worker const CPUInfo& CPUInfo::Get() {
854*dbb99499SAndroid Build Coastguard Worker static const CPUInfo* info = new CPUInfo();
855*dbb99499SAndroid Build Coastguard Worker return *info;
856*dbb99499SAndroid Build Coastguard Worker }
857*dbb99499SAndroid Build Coastguard Worker
CPUInfo()858*dbb99499SAndroid Build Coastguard Worker CPUInfo::CPUInfo()
859*dbb99499SAndroid Build Coastguard Worker : num_cpus(GetNumCPUs()),
860*dbb99499SAndroid Build Coastguard Worker scaling(CpuScaling(num_cpus)),
861*dbb99499SAndroid Build Coastguard Worker cycles_per_second(GetCPUCyclesPerSecond(scaling)),
862*dbb99499SAndroid Build Coastguard Worker caches(GetCacheSizes()),
863*dbb99499SAndroid Build Coastguard Worker load_avg(GetLoadAvg()) {}
864*dbb99499SAndroid Build Coastguard Worker
Get()865*dbb99499SAndroid Build Coastguard Worker const SystemInfo& SystemInfo::Get() {
866*dbb99499SAndroid Build Coastguard Worker static const SystemInfo* info = new SystemInfo();
867*dbb99499SAndroid Build Coastguard Worker return *info;
868*dbb99499SAndroid Build Coastguard Worker }
869*dbb99499SAndroid Build Coastguard Worker
SystemInfo()870*dbb99499SAndroid Build Coastguard Worker SystemInfo::SystemInfo() : name(GetSystemName()) {}
871*dbb99499SAndroid Build Coastguard Worker } // end namespace benchmark
872