18 #ifdef BENCHMARK_OS_WINDOWS
20 #include <VersionHelpers.h>
24 #include <sys/resource.h>
26 #include <sys/types.h>
28 #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
29 #include <sys/sysctl.h>
53 double cpuinfo_cycles_per_second = 1.0;
54 int cpuinfo_num_cpus = 1;
56 #if !defined BENCHMARK_OS_MACOSX
57 const int64_t estimate_time_ms = 1000;
61 int64_t EstimateCyclesPerSecond() {
68 #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
71 bool ReadIntFromFile(
const char*
file,
long*
value) {
81 const long temp_value = strtol(
line, &
err, 10);
82 if (
line[0] !=
'\0' && (*
err ==
'\n' || *
err ==
'\0')) {
92 #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
95 ch = std::tolower(
ch);
99 bool IgnoreCase =
true) {
108 void InitializeSystemInfo() {
109 #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
114 bool saw_mhz =
false;
123 ReadIntFromFile(
"/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
126 cpuinfo_cycles_per_second = freq * 1000.0;
133 ReadIntFromFile(
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
137 cpuinfo_cycles_per_second = freq * 1000.0;
142 const char* pname =
"/proc/cpuinfo";
143 int fd =
open(pname, O_RDONLY);
147 cpuinfo_cycles_per_second =
148 static_cast<double>(EstimateCyclesPerSecond());
153 double bogo_clock = 1.0;
154 bool saw_bogo =
false;
158 size_t chars_read = 0;
161 const size_t oldlinelen = strlen(
line);
162 if (
sizeof(
line) == oldlinelen + 1)
165 memmove(
line,
line + oldlinelen + 1,
sizeof(
line) - (oldlinelen + 1));
167 char* newline = strchr(
line,
'\n');
168 if (newline ==
nullptr) {
169 const size_t linelen = strlen(
line);
170 const size_t bytes_to_read =
sizeof(
line) - 1 - linelen;
171 CHECK(bytes_to_read > 0);
172 chars_read =
read(fd,
line + linelen, bytes_to_read);
173 line[linelen + chars_read] =
'\0';
174 newline = strchr(
line,
'\n');
176 if (newline !=
nullptr) *newline =
'\0';
181 if (!saw_mhz && startsWithKey(
line,
"cpu MHz")) {
182 const char* freqstr = strchr(
line,
':');
184 cpuinfo_cycles_per_second = strtod(freqstr + 1, &
err) * 1000000.0;
185 if (freqstr[1] !=
'\0' && *
err ==
'\0' && cpuinfo_cycles_per_second > 0)
188 }
else if (startsWithKey(
line,
"bogomips")) {
189 const char* freqstr = strchr(
line,
':');
191 bogo_clock = strtod(freqstr + 1, &
err) * 1000000.0;
192 if (freqstr[1] !=
'\0' && *
err ==
'\0' && bogo_clock > 0)
195 }
else if (startsWithKey(
line,
"processor",
false)) {
201 const char* id_str = strchr(
line,
':');
203 const long cpu_id = strtol(id_str + 1, &
err, 10);
204 if (id_str[1] !=
'\0' && *
err ==
'\0' && max_cpu_id < cpu_id)
208 }
while (chars_read > 0);
215 cpuinfo_cycles_per_second = bogo_clock;
218 cpuinfo_cycles_per_second =
219 static_cast<double>(EstimateCyclesPerSecond());
223 fprintf(
stderr,
"Failed to read num. CPUs correctly from /proc/cpuinfo\n");
227 "CPU ID assignments in /proc/cpuinfo seem messed up."
228 " This is usually caused by a bad BIOS.\n");
233 #elif defined BENCHMARK_OS_FREEBSD
250 size_t sz =
sizeof(hz);
251 const char* sysctl_path =
"machdep.tsc_freq";
252 if (sysctlbyname(sysctl_path, &hz, &sz,
nullptr, 0) != 0) {
253 fprintf(
stderr,
"Unable to determine clock rate from sysctl: %s: %s\n",
254 sysctl_path, strerror(errno));
255 cpuinfo_cycles_per_second =
static_cast<double>(EstimateCyclesPerSecond());
257 cpuinfo_cycles_per_second = hz;
261 #elif defined BENCHMARK_OS_WINDOWS
264 DWORD
data, data_size =
sizeof(
data);
265 if (IsWindowsXPOrGreater() &&
267 SHGetValueA(HKEY_LOCAL_MACHINE,
268 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
269 "~MHz",
nullptr, &
data, &data_size)))
270 cpuinfo_cycles_per_second =
273 cpuinfo_cycles_per_second =
static_cast<double>(EstimateCyclesPerSecond());
279 GetSystemInfo(&sysinfo);
280 cpuinfo_num_cpus = sysinfo.dwNumberOfProcessors;
284 #elif defined BENCHMARK_OS_MACOSX
287 if (::sysctlbyname(
"hw.ncpu", &
num_cpus, &
size,
nullptr, 0) == 0 &&
291 fprintf(
stderr,
"%s\n", strerror(errno));
292 std::exit(EXIT_FAILURE);
295 size =
sizeof(cpu_freq);
296 if (::sysctlbyname(
"hw.cpufrequency", &cpu_freq, &
size,
nullptr, 0) == 0 &&
297 (
size ==
sizeof(cpu_freq))) {
298 cpuinfo_cycles_per_second = cpu_freq;
300 #if defined BENCHMARK_OS_IOS
301 fprintf(
stderr,
"CPU frequency cannot be detected. \n");
302 cpuinfo_cycles_per_second = 0;
304 fprintf(
stderr,
"%s\n", strerror(errno));
305 std::exit(EXIT_FAILURE);
310 cpuinfo_cycles_per_second =
static_cast<double>(EstimateCyclesPerSecond());
318 return cpuinfo_cycles_per_second;
323 return cpuinfo_num_cpus;
327 #define strliterallen(str) (sizeof("" str "") - 1)
330 #define memprefix(str, len, prefix) \
331 ((((len) >= strliterallen(prefix)) && \
332 std::memcmp(str, prefix, strliterallen(prefix)) == 0) \
333 ? str + strliterallen(prefix) \
337 #ifndef BENCHMARK_OS_WINDOWS
343 StrCat(
"/sys/devices/system/cpu/cpu", cpu,
"/cpufreq/scaling_governor");
344 FILE*
file = fopen(governor_file.c_str(),
"r");