https://github.com/google/benchmark/commit/f65741b2bd92461dc2c816056eb9c996ae48ad62 https://github.com/google/benchmark/commit/077db43001b42af3ad23e993b2bdcb4fadb7bcf8 https://github.com/google/benchmark/commit/39be87d3004ff9ff4cdf736651af80c3d15e2497 https://github.com/google/benchmark/commit/c24774dc4f4402c3ad150363321cc972ed2669e7 From f65741b2bd92461dc2c816056eb9c996ae48ad62 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 8 Jan 2025 13:03:53 +0100 Subject: [PATCH] cycleclock: Support for PA-RISC (hppa) architecture (#1894) Co-authored-by: dominic <510002+dmah42@users.noreply.github.com> --- src/cycleclock.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cycleclock.h b/src/cycleclock.h index bd62f5d7e7..7852f3df52 100644 --- a/src/cycleclock.h +++ b/src/cycleclock.h @@ -229,6 +229,16 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { struct timeval tv; gettimeofday(&tv, nullptr); return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; +#elif defined(__hppa__) + // HP PA-RISC provides a user-readable clock counter (cr16), but + // it's not syncronized across CPUs and only 32-bit wide when programs + // are built as 32-bit binaries. + // Use clock_gettime(CLOCK_MONOTONIC, ...) instead of gettimeofday + // because is provides nanosecond resolution. + // Initialize to always return 0 if clock_gettime fails. + struct timespec ts = {0, 0}; + clock_gettime(CLOCK_MONOTONIC, &ts); + return static_cast(ts.tv_sec) * 1000000000 + ts.tv_nsec; #else // The soft failover to a generic implementation is automatic only for ARM. // For other platforms the developer is expected to make an attempt to create From 077db43001b42af3ad23e993b2bdcb4fadb7bcf8 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 8 Jan 2025 17:54:08 +0100 Subject: [PATCH] cycleclock: Use cock_gettime() as fallback for any Linux architecture (#1899) The Linux kernel provides the clock_gettime() functions since a long time already, so it's possible to use it as a generic fallback option for any architecture if no other (better) possibility has been provided instead. I noticed the benchmark package failed to build on debian on the SH-4 architecture, so with this change SH-4 is now the first user of this fallback option. --- src/cycleclock.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cycleclock.h b/src/cycleclock.h index 7852f3df5..03e02f805 100644 --- a/src/cycleclock.h +++ b/src/cycleclock.h @@ -229,10 +229,12 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { struct timeval tv; gettimeofday(&tv, nullptr); return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; -#elif defined(__hppa__) +#elif defined(__hppa__) || defined(__linux__) + // Fallback for all other architectures with a recent Linux kernel, e.g.: // HP PA-RISC provides a user-readable clock counter (cr16), but // it's not syncronized across CPUs and only 32-bit wide when programs // are built as 32-bit binaries. + // Same for SH-4 and possibly others. // Use clock_gettime(CLOCK_MONOTONIC, ...) instead of gettimeofday // because is provides nanosecond resolution. // Initialize to always return 0 if clock_gettime fails. From 39be87d3004ff9ff4cdf736651af80c3d15e2497 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 9 Jan 2025 11:47:29 +0100 Subject: [PATCH] Fix runtime crash when parsing /proc/cpuinfo fails (#1900) The testcase fails on sparc64, because the parsing of /proc/cpuinfo fails and thus currently returns "0" CPUs which finally leads to division-by-zero faults in the tests. Fix the issue by returning at least "1" CPU which allows the tests to run. A error message will be printed in any case. Long-term the code should be fixed to parse the cpuinfo output on sparch which looks like this: ... type : sun4v ncpus probed : 48 ncpus active : 48 --- src/sysinfo.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sysinfo.cc b/src/sysinfo.cc index 49bff75e5..ce14b8d8e 100644 --- a/src/sysinfo.cc +++ b/src/sysinfo.cc @@ -561,10 +561,12 @@ int GetNumCPUsImpl() { } int GetNumCPUs() { - const int num_cpus = GetNumCPUsImpl(); + int num_cpus = GetNumCPUsImpl(); if (num_cpus < 1) { std::cerr << "Unable to extract number of CPUs. If your platform uses " "/proc/cpuinfo, custom support may need to be added.\n"; + /* There is at least one CPU which we run on. */ + num_cpus = 1; } return num_cpus; } From c24774dc4f4402c3ad150363321cc972ed2669e7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 9 Jan 2025 17:07:43 +0100 Subject: [PATCH] Get number of CPUs with sysconf() on Linux (#1901) * Get number of CPUs with sysconf() on Linux Avoid parsing the /proc/cpuinfo just to get number of CPUs. Instead use the portable function provided by glibc. * Update sysinfo.cc --- src/sysinfo.cc | 54 +++----------------------------------------------- 1 file changed, 3 insertions(+), 51 deletions(-) diff --git a/src/sysinfo.cc b/src/sysinfo.cc index ce14b8d8e..eddd430e6 100644 --- a/src/sysinfo.cc +++ b/src/sysinfo.cc @@ -492,14 +492,14 @@ int GetNumCPUsImpl() { GetSystemInfo(&sysinfo); // number of logical processors in the current group return static_cast(sysinfo.dwNumberOfProcessors); -#elif defined(BENCHMARK_OS_SOLARIS) +#elif defined(__linux__) || defined(BENCHMARK_OS_SOLARIS) // Returns -1 in case of a failure. - long num_cpu = sysconf(_SC_NPROCESSORS_ONLN); + int num_cpu = static_cast(sysconf(_SC_NPROCESSORS_ONLN)); if (num_cpu < 0) { PrintErrorAndDie("sysconf(_SC_NPROCESSORS_ONLN) failed with error: ", strerror(errno)); } - return (int)num_cpu; + return num_cpu; #elif defined(BENCHMARK_OS_QNX) return static_cast(_syspage_ptr->num_cpu); #elif defined(BENCHMARK_OS_QURT) @@ -508,54 +508,6 @@ int GetNumCPUsImpl() { hardware_threads.max_hthreads = 1; } return hardware_threads.max_hthreads; -#else - int num_cpus = 0; - int max_id = -1; - std::ifstream f("/proc/cpuinfo"); - if (!f.is_open()) { - std::cerr << "Failed to open /proc/cpuinfo\n"; - return -1; - } -#if defined(__alpha__) - const std::string Key = "cpus detected"; -#else - const std::string Key = "processor"; -#endif - std::string ln; - while (std::getline(f, ln)) { - if (ln.empty()) continue; - std::size_t split_idx = ln.find(':'); - std::string value; -#if defined(__s390__) - // s390 has another format in /proc/cpuinfo - // it needs to be parsed differently - if (split_idx != std::string::npos) - value = ln.substr(Key.size() + 1, split_idx - Key.size() - 1); -#else - if (split_idx != std::string::npos) value = ln.substr(split_idx + 1); -#endif - if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) { - num_cpus++; - if (!value.empty()) { - const int cur_id = benchmark::stoi(value); - max_id = std::max(cur_id, max_id); - } - } - } - if (f.bad()) { - PrintErrorAndDie("Failure reading /proc/cpuinfo"); - } - if (!f.eof()) { - PrintErrorAndDie("Failed to read to end of /proc/cpuinfo"); - } - f.close(); - - if ((max_id + 1) != num_cpus) { - fprintf(stderr, - "CPU ID assignments in /proc/cpuinfo seem messed up." - " This is usually caused by a bad BIOS.\n"); - } - return num_cpus; #endif BENCHMARK_UNREACHABLE(); }