xref: /aosp_15_r20/external/google-benchmark/src/sysinfo.cc (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
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