Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tf: aarch64 fix for cases where CNTFRQ_EL0 returns bogus value #2929

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pxr/base/arch/testenv/testTiming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ PXR_NAMESPACE_USING_DIRECTIVE

int main()
{
ARCH_AXIOM(ArchGetNanosecondsPerTick() > 0.0);
// If you're not even doing 1 tick a second, it's probably a bogus value
ARCH_AXIOM(ArchGetNanosecondsPerTick() < 1e9);
// Verify conversions for many tick counts.
for (size_t ticks = 0ul; ticks != 1ul << 24u; ++ticks) {
ARCH_AXIOM( (uint64_t) ArchTicksToNanoseconds(ticks) ==
Expand Down
20 changes: 17 additions & 3 deletions pxr/base/arch/timing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,23 @@ Arch_ComputeNanosecondsPerTick()
#if defined(ARCH_CPU_ARM)
uint64_t counter_hz;
__asm __volatile("mrs %0, CNTFRQ_EL0" : "=&r" (counter_hz));
Arch_NanosecondsPerTick = double(1e9) / double(counter_hz);
#else

// As noted in this commit in the linux kernel:
//
// https://github.com/torvalds/linux/commit/c6f97add0f2ac83b98b06dbdda58fa47638ae7b0
//
// ...the value of CNTFRQ_EL0 is sometimes unreliable. The linux kernel
// instead reads the tick rate from the device tree, and if that fails,
// only then falls back on CNTFRQ_EL0.
//
// Since we already have measurement-based code, and reading from the device
// tree seemed tricky, we instead check if CNTFRQ_EL0 seems "sane"
// (ie, > 1Hz), and if not, fall back on the measurement code used in all
// other linux flavors.
if (counter_hz > 1) {
return double(1e9) / double(counter_hz);
}
#endif

// Measure how long it takes to call ::now().
uint64_t nowDuration =
Expand All @@ -135,7 +150,6 @@ Arch_ComputeNanosecondsPerTick()
// as the overhead to call now() one time.
return clockNanoSecs /
double(ticks - ArchGetIntervalTimerTickOverhead() - nowDuration);
#endif
}
#elif defined(ARCH_OS_WINDOWS)

Expand Down