Skip to content

Commit c9572d1

Browse files
fujitajannau
authored andcommitted
rust: time: Avoid 64-bit integer division on 32-bit architectures
Avoid 64-bit integer division that 32-bit architectures don't implement generally. This uses ktime_to_us() and ktime_to_ms() instead. The time abstraction needs i64 / u32 division so C's div_s64() can be used but ktime_to_us() and ktime_to_ms() provide a simpler solution for this time abstraction problem on 32-bit architectures. 32-bit ARM is the only 32-bit architecture currently supported by Rust. Using the cfg attribute, only 32-bit architectures will call ktime_to_us() and ktime_to_ms(), while the other 64-bit architectures will continue to use the current code as-is to avoid the overhead. One downside of calling the C's functions is that the as_micros/millis methods can no longer be const fn. We stick with the simpler approach unless there's a compelling need for a const fn. Suggested-by: Arnd Bergmann <arnd@arndb.de> Suggested-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250502004524.230553-1-fujita.tomonori@gmail.com Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
1 parent b663117 commit c9572d1

3 files changed

Lines changed: 36 additions & 4 deletions

File tree

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "spinlock.c"
3939
#include "sync.c"
4040
#include "task.c"
41+
#include "time.c"
4142
#include "uaccess.c"
4243
#include "vmalloc.c"
4344
#include "wait.c"

rust/helpers/time.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/ktime.h>
4+
5+
s64 rust_helper_ktime_to_us(const ktime_t kt)
6+
{
7+
return ktime_to_us(kt);
8+
}
9+
10+
s64 rust_helper_ktime_to_ms(const ktime_t kt)
11+
{
12+
return ktime_to_ms(kt);
13+
}

rust/kernel/time.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,31 @@ impl Delta {
228228
/// Return the smallest number of microseconds greater than or equal
229229
/// to the value in the [`Delta`].
230230
#[inline]
231-
pub const fn as_micros_ceil(self) -> i64 {
232-
self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC
231+
pub fn as_micros_ceil(self) -> i64 {
232+
#[cfg(CONFIG_64BIT)]
233+
{
234+
self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC
235+
}
236+
237+
#[cfg(not(CONFIG_64BIT))]
238+
// SAFETY: It is always safe to call `ktime_to_us()` with any value.
239+
unsafe {
240+
bindings::ktime_to_us(self.as_nanos().saturating_add(NSEC_PER_USEC - 1))
241+
}
233242
}
234243

235244
/// Return the number of milliseconds in the [`Delta`].
236245
#[inline]
237-
pub const fn as_millis(self) -> i64 {
238-
self.as_nanos() / NSEC_PER_MSEC
246+
pub fn as_millis(self) -> i64 {
247+
#[cfg(CONFIG_64BIT)]
248+
{
249+
self.as_nanos() / NSEC_PER_MSEC
250+
}
251+
252+
#[cfg(not(CONFIG_64BIT))]
253+
// SAFETY: It is always safe to call `ktime_to_ms()` with any value.
254+
unsafe {
255+
bindings::ktime_to_ms(self.as_nanos())
256+
}
239257
}
240258
}

0 commit comments

Comments
 (0)