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

unscaledcycleclock: use RDTIME instead of RDCYCLE on RISC-V #1631

Closed
wants to merge 1 commit into from

Conversation

aurel32
Copy link
Contributor

@aurel32 aurel32 commented Feb 29, 2024

Starting with Linux 6.6 [1], RDCYCLE is a privileged instruction on RISC-V and can't be used directly from userland. There is a sysctl option to change that as a transition period, but it will eventually disappear.

Use RDTIME instead, which while less accurate has the advantage of being synchronized between CPU (and thus monotonic) and of constant frequency. Therefore this change also fixes another issue caused by wrong time measurement when a process is rescheduled from one CPU to another [2].

Given RDTIME uses a timer independent from the CPU, this patche removes the ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY define accordingly.

This fixes the testsuite on riscv64, tested on a VisionFive 2 board.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc4c07c89aada16229084eeb93895c95b7eabaa3
[2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1025221

Starting with Linux 6.6 [1], RDCYCLE is a privileged instruction on
RISC-V and can't be used directly from userland. There is a sysctl
option to change that as a transition period, but it will eventually
disappear.

Use RDTIME instead, which while less accurate has the advantage of being
synchronized between CPU (and thus monotonic) and of constant frequency.
Therefore this change also fixes another issue caused by wrong time
measurement when a process is rescheduled from one CPU to another [2].

Given RDTIME uses a timer independent from the CPU, this patche removes
the ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY define
accordingly.

This fixes the testsuite on riscv64, tested on a VisionFive 2 board.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc4c07c89aada16229084eeb93895c95b7eabaa3
[2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1025221
@@ -53,7 +53,7 @@
#if ABSL_USE_UNSCALED_CYCLECLOCK
// This macro can be used to test if UnscaledCycleClock::Frequency()
// is NominalCPUFrequency() on a particular platform.
#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
#if (defined(__i386__) || defined(__x86_64__) || \
defined(_M_IX86) || defined(_M_X64))
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need an implementation of UnscaledCycleClock::Frequency() now that these are not the same thing. The code in this repo may not call that method, but code exists that does.

https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf says

The RDTIME pseudo-instruction reads the low XLEN bits of the time CSR, which counts wall-clock
real time that has passed from an arbitrary start time in the past. RDTIMEH is an RV32I-only instruction that reads bits 63–32 of the same real-time counter. The underlying 64-bit counter should
never overflow in practice. The execution environment should provide a means of determining the
period of the real-time counter (seconds/tick). The period must be constant. The real-time clocks
of all hardware threads in a single user application should be synchronized to within one tick of the
real-time clock. The environment should provide a means to determine the accuracy of the clock.

I have no idea how to get that.

If you are just trying to get something to build, -DABSL_USE_UNSCALED_CYCLECLOCK=0 should work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The frequency is implementation dependent, and there is no easy way to get it. Could it be measured instead? Basically how it is done for the ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY?

aurel32 added a commit to aurel32/abseil-cpp that referenced this pull request Mar 19, 2024
Starting with Linux 6.6 [1], RDCYCLE is a privileged instruction on
RISC-V and can't be used directly from userland. There is a sysctl
option to change that as a transition period, but it will eventually
disappear.

The RDTIME instruction is another less accurate alternative, however its
frequency varies from board to board, and there is currently now way to
get its frequency from userland [2].

Therefore this patch just removes the code for unscaledcycleclock on
RISC-V. Without processor specific implementation, abseil relies on
std::chrono::steady_clock::now().time_since_epoch() which is basically a
wrapper around clock_gettime (CLOCK_MONOTONIC), which in turns use
__vdso_clock_gettime(). On RISC-V this VDSO is just a wrapper around
RDTIME correctly scaled to use nanoseconds units.

This fixes the testsuite on riscv64, tested on a VisionFive 2 board.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc4c07c89aada16229084eeb93895c95b7eabaa3
[2] abseil#1631
@aurel32
Copy link
Contributor Author

aurel32 commented Mar 19, 2024

Closing in favor of #1644

@aurel32 aurel32 closed this Mar 19, 2024
copybara-service bot pushed a commit that referenced this pull request Mar 22, 2024
Imported from GitHub PR #1644

Starting with Linux 6.6 [1], RDCYCLE is a privileged instruction on RISC-V and can't be used directly from userland. There is a sysctl option to change that as a transition period, but it will eventually disappear.

The RDTIME instruction is another less accurate alternative, however its frequency varies from board to board, and there is currently now way to get its frequency from userland [2].

Therefore this patch just removes the code for unscaledcycleclock on RISC-V. Without processor specific implementation, abseil relies on std::chrono::steady_clock::now().time_since_epoch() which is basically a wrapper around clock_gettime (CLOCK_MONOTONIC), which in turns use __vdso_clock_gettime(). On RISC-V this VDSO is just a wrapper around RDTIME correctly scaled to use nanoseconds units.

This fixes the testsuite on riscv64, tested on a VisionFive 2 board.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc4c07c89aada16229084eeb93895c95b7eabaa3
[2] #1631
Merge 43356a2 into 76f8011

Merging this change closes #1644

COPYBARA_INTEGRATE_REVIEW=#1644 from aurel32:rv64-no-unscaledcycleclock 43356a2
PiperOrigin-RevId: 618286262
Change-Id: Ie4120a727e7d0bb185df6e06ea145c780ebe6652
netkex pushed a commit to netkex/abseil-cpp that referenced this pull request Apr 3, 2024
Imported from GitHub PR abseil#1644

Starting with Linux 6.6 [1], RDCYCLE is a privileged instruction on RISC-V and can't be used directly from userland. There is a sysctl option to change that as a transition period, but it will eventually disappear.

The RDTIME instruction is another less accurate alternative, however its frequency varies from board to board, and there is currently now way to get its frequency from userland [2].

Therefore this patch just removes the code for unscaledcycleclock on RISC-V. Without processor specific implementation, abseil relies on std::chrono::steady_clock::now().time_since_epoch() which is basically a wrapper around clock_gettime (CLOCK_MONOTONIC), which in turns use __vdso_clock_gettime(). On RISC-V this VDSO is just a wrapper around RDTIME correctly scaled to use nanoseconds units.

This fixes the testsuite on riscv64, tested on a VisionFive 2 board.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc4c07c89aada16229084eeb93895c95b7eabaa3
[2] abseil#1631
Merge 43356a2 into 76f8011

Merging this change closes abseil#1644

COPYBARA_INTEGRATE_REVIEW=abseil#1644 from aurel32:rv64-no-unscaledcycleclock 43356a2
PiperOrigin-RevId: 618286262
Change-Id: Ie4120a727e7d0bb185df6e06ea145c780ebe6652
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants