From d2a8a4ee41b923876c034afb939c4fc03598e622 Mon Sep 17 00:00:00 2001 From: Marat Dukhan Date: Tue, 4 Oct 2022 12:43:27 -0700 Subject: [PATCH] Support for QuRT OS (Hexagon RTOS) (#1497) --- include/benchmark/benchmark.h | 7 +++++++ src/benchmark.cc | 2 +- src/benchmark_register.cc | 2 +- src/benchmark_runner.cc | 2 +- src/cycleclock.h | 4 ++++ src/internal_macros.h | 2 ++ src/reporter.cc | 4 ++++ src/sysinfo.cc | 26 ++++++++++++++++++++++++-- src/timers.cc | 15 +++++++++++++-- 9 files changed, 57 insertions(+), 7 deletions(-) diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h index bc426ca3..fefe9b20 100644 --- a/include/benchmark/benchmark.h +++ b/include/benchmark/benchmark.h @@ -1534,8 +1534,15 @@ class Fixture : public internal::Benchmark { #endif // Helper macro to create a main routine in a test that runs the benchmarks +// Note the workaround for Hexagon simulator passing argc != 0, argv = NULL. #define BENCHMARK_MAIN() \ int main(int argc, char** argv) { \ + char arg0_default[] = "benchmark"; \ + char* args_default = arg0_default; \ + if (!argv) { \ + argc = 1; \ + argv = &args_default; \ + } \ ::benchmark::Initialize(&argc, argv); \ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \ ::benchmark::RunSpecifiedBenchmarks(); \ diff --git a/src/benchmark.cc b/src/benchmark.cc index f18c3081..ff286480 100644 --- a/src/benchmark.cc +++ b/src/benchmark.cc @@ -19,7 +19,7 @@ #include "internal_macros.h" #ifndef BENCHMARK_OS_WINDOWS -#ifndef BENCHMARK_OS_FUCHSIA +#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) #include #endif #include diff --git a/src/benchmark_register.cc b/src/benchmark_register.cc index a42b7668..eae2c320 100644 --- a/src/benchmark_register.cc +++ b/src/benchmark_register.cc @@ -15,7 +15,7 @@ #include "benchmark_register.h" #ifndef BENCHMARK_OS_WINDOWS -#ifndef BENCHMARK_OS_FUCHSIA +#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) #include #endif #include diff --git a/src/benchmark_runner.cc b/src/benchmark_runner.cc index 0fb74bfa..fd6da53f 100644 --- a/src/benchmark_runner.cc +++ b/src/benchmark_runner.cc @@ -19,7 +19,7 @@ #include "internal_macros.h" #ifndef BENCHMARK_OS_WINDOWS -#ifndef BENCHMARK_OS_FUCHSIA +#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) #include #endif #include diff --git a/src/cycleclock.h b/src/cycleclock.h index 04f094fe..df6ffa51 100644 --- a/src/cycleclock.h +++ b/src/cycleclock.h @@ -212,6 +212,10 @@ 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(__hexagon__) + uint64_t pcycle; + asm volatile("%0 = C15:14" : "=r"(pcycle)); + return static_cast(pcycle); #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 diff --git a/src/internal_macros.h b/src/internal_macros.h index 1fe1eb6a..396a390a 100644 --- a/src/internal_macros.h +++ b/src/internal_macros.h @@ -85,6 +85,8 @@ #define BENCHMARK_OS_QNX 1 #elif defined(__MVS__) #define BENCHMARK_OS_ZOS 1 +#elif defined(__hexagon__) +#define BENCHMARK_OS_QURT 1 #endif #if defined(__ANDROID__) && defined(__GLIBCXX__) diff --git a/src/reporter.cc b/src/reporter.cc index 8b5fdaff..076bc31a 100644 --- a/src/reporter.cc +++ b/src/reporter.cc @@ -36,7 +36,11 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, BM_CHECK(out) << "cannot be null"; auto &Out = *out; +#ifndef BENCHMARK_OS_QURT + // Date/time information is not available on QuRT. + // Attempting to get it via this call cause the binary to crash. Out << LocalDateTimeString() << "\n"; +#endif if (context.executable_name) Out << "Running " << context.executable_name << "\n"; diff --git a/src/sysinfo.cc b/src/sysinfo.cc index b91739b1..41f2d36e 100644 --- a/src/sysinfo.cc +++ b/src/sysinfo.cc @@ -23,7 +23,7 @@ #include #else #include -#ifndef BENCHMARK_OS_FUCHSIA +#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) #include #endif #include @@ -42,6 +42,9 @@ #if defined(BENCHMARK_OS_QNX) #include #endif +#if defined(BENCHMARK_OS_QURT) +#include +#endif #include #include @@ -402,6 +405,8 @@ std::vector GetCacheSizes() { return GetCacheSizesWindows(); #elif defined(BENCHMARK_OS_QNX) return GetCacheSizesQNX(); +#elif defined(BENCHMARK_OS_QURT) + return std::vector(); #else return GetCacheSizesFromKVFS(); #endif @@ -432,7 +437,15 @@ std::string GetSystemName() { str = std::string(converted.data()); #endif return str; -#else // defined(BENCHMARK_OS_WINDOWS) +#elif defined(BENCHMARK_OS_QURT) + std::string str = "Hexagon DSP"; + qurt_arch_version_t arch_version_struct; + if (qurt_sysenv_get_arch_version(&arch_version_struct) == QURT_EOK) { + str += " v"; + str += std::to_string(arch_version_struct.arch_version); + } + return str; +#else #ifndef HOST_NAME_MAX #ifdef BENCHMARK_HAS_SYSCTL // BSD/Mac Doesnt have HOST_NAME_MAX defined #define HOST_NAME_MAX 64 @@ -479,6 +492,12 @@ int GetNumCPUs() { return num_cpu; #elif defined(BENCHMARK_OS_QNX) return static_cast(_syspage_ptr->num_cpu); +#elif defined(BENCHMARK_OS_QURT) + qurt_sysenv_max_hthreads_t hardware_threads; + if (qurt_sysenv_get_max_hw_threads(&hardware_threads) != QURT_EOK) { + hardware_threads.max_hthreads = 1; + } + return hardware_threads.max_hthreads; #else int num_cpus = 0; int max_id = -1; @@ -678,6 +697,9 @@ double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { #elif defined(BENCHMARK_OS_QNX) return static_cast((int64_t)(SYSPAGE_ENTRY(cpuinfo)->speed) * (int64_t)(1000 * 1000)); +#elif defined(BENCHMARK_OS_QURT) + // QuRT doesn't provide any API to query Hexagon frequency. + return 1000000000; #endif // If we've fallen through, attempt to roughly estimate the CPU clock rate. static constexpr int estimate_time_ms = 1000; diff --git a/src/timers.cc b/src/timers.cc index 68612e26..379d97dd 100644 --- a/src/timers.cc +++ b/src/timers.cc @@ -23,7 +23,7 @@ #include #else #include -#ifndef BENCHMARK_OS_FUCHSIA +#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) #include #endif #include @@ -38,6 +38,9 @@ #include #include #endif +#if defined(BENCHMARK_OS_QURT) +#include +#endif #endif #ifdef BENCHMARK_OS_EMSCRIPTEN @@ -79,7 +82,7 @@ double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) { static_cast(user.QuadPart)) * 1e-7; } -#elif !defined(BENCHMARK_OS_FUCHSIA) +#elif !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) double MakeTime(struct rusage const& ru) { return (static_cast(ru.ru_utime.tv_sec) + static_cast(ru.ru_utime.tv_usec) * 1e-6 + @@ -119,6 +122,10 @@ double ProcessCPUUsage() { &user_time)) return MakeTime(kernel_time, user_time); DiagnoseAndExit("GetProccessTimes() failed"); +#elif defined(BENCHMARK_OS_QURT) + return static_cast( + qurt_timer_timetick_to_us(qurt_timer_get_ticks())) * + 1.0e-6; #elif defined(BENCHMARK_OS_EMSCRIPTEN) // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten. // Use Emscripten-specific API. Reported CPU time would be exactly the @@ -149,6 +156,10 @@ double ThreadCPUUsage() { GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time, &user_time); return MakeTime(kernel_time, user_time); +#elif defined(BENCHMARK_OS_QURT) + return static_cast( + qurt_timer_timetick_to_us(qurt_timer_get_ticks())) * + 1.0e-6; #elif defined(BENCHMARK_OS_MACOSX) // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. // See https://github.com/google/benchmark/pull/292