Improve compatibility with Hexagon hardware (#1785)

The customization done via BENCHMARK_OS_QURT works just fine with the Hexagon simulator, but on at least some Hexagon hardware, both `qurt_timer_get_ticks()` and `std::chrono::now()` are broken and always return 0. This fixes the former by using the better-supported (and essentially identical `qurt_sysclock_get_hw_ticks()` call, and the latter by reading a 19.2MHz hardware counter (per suggestion from Qualcomm). Local testing seems to indicate these changes are just as robust under the simulator as before.
This commit is contained in:
Steven Johnson 2024-05-23 10:08:54 -07:00 committed by GitHub
parent a4cf155615
commit 7f992a553d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 3 deletions

View File

@ -126,8 +126,12 @@ double ProcessCPUUsage() {
return MakeTime(kernel_time, user_time);
DiagnoseAndExit("GetProccessTimes() failed");
#elif defined(BENCHMARK_OS_QURT)
// Note that qurt_timer_get_ticks() is no longer documented as of SDK 5.3.0,
// and doesn't appear to work on at least some devices (eg Samsung S22),
// so let's use the actually-documented and apparently-equivalent
// qurt_sysclock_get_hw_ticks() call instead.
return static_cast<double>(
qurt_timer_timetick_to_us(qurt_timer_get_ticks())) *
qurt_timer_timetick_to_us(qurt_sysclock_get_hw_ticks())) *
1.0e-6;
#elif defined(BENCHMARK_OS_EMSCRIPTEN)
// clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten.
@ -160,8 +164,12 @@ double ThreadCPUUsage() {
&user_time);
return MakeTime(kernel_time, user_time);
#elif defined(BENCHMARK_OS_QURT)
// Note that qurt_timer_get_ticks() is no longer documented as of SDK 5.3.0,
// and doesn't appear to work on at least some devices (eg Samsung S22),
// so let's use the actually-documented and apparently-equivalent
// qurt_sysclock_get_hw_ticks() call instead.
return static_cast<double>(
qurt_timer_timetick_to_us(qurt_timer_get_ticks())) *
qurt_timer_timetick_to_us(qurt_sysclock_get_hw_ticks())) *
1.0e-6;
#elif defined(BENCHMARK_OS_MACOSX)
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11.

View File

@ -15,6 +15,29 @@ double ChildrenCPUUsage();
// Return the CPU usage of the current thread
double ThreadCPUUsage();
#if defined(BENCHMARK_OS_QURT)
// std::chrono::now() can return 0 on some Hexagon devices;
// this reads the value of a 56-bit, 19.2MHz hardware counter
// and converts it to seconds. Unlike std::chrono, this doesn't
// return an absolute time, but since ChronoClockNow() is only used
// to compute elapsed time, this shouldn't matter.
struct QuRTClock {
typedef uint64_t rep;
typedef std::ratio<1, 19200000> period;
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<QuRTClock> time_point;
static const bool is_steady = false;
static time_point now() {
unsigned long long count;
asm volatile(" %0 = c31:30 " : "=r"(count));
return time_point(static_cast<duration>(count));
}
};
#else
#if defined(HAVE_STEADY_CLOCK)
template <bool HighResIsSteady = std::chrono::high_resolution_clock::is_steady>
struct ChooseSteadyClock {
@ -25,10 +48,14 @@ template <>
struct ChooseSteadyClock<false> {
typedef std::chrono::steady_clock type;
};
#endif // HAVE_STEADY_CLOCK
#endif
struct ChooseClockType {
#if defined(HAVE_STEADY_CLOCK)
#if defined(BENCHMARK_OS_QURT)
typedef QuRTClock type;
#elif defined(HAVE_STEADY_CLOCK)
typedef ChooseSteadyClock<>::type type;
#else
typedef std::chrono::high_resolution_clock type;