linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Russell King (Oracle)" <linux@armlinux.org.uk>
To: Christian Schrefl <chrisi.schrefl@gmail.com>
Cc: FUJITA Tomonori <fujita.tomonori@gmail.com>,
	a.hindborg@kernel.org, rust-for-linux@vger.kernel.org,
	gary@garyguo.net, aliceryhl@google.com, me@kloenk.dev,
	daniel.almeida@collabora.com, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org, andrew@lunn.ch, hkallweit1@gmail.com,
	tmgross@umich.edu, ojeda@kernel.org, alex.gaynor@gmail.com,
	bjorn3_gh@protonmail.com, benno.lossin@proton.me,
	a.hindborg@samsung.com, anna-maria@linutronix.de,
	frederic@kernel.org, tglx@linutronix.de, arnd@arndb.de,
	jstultz@google.com, sboyd@kernel.org, mingo@redhat.com,
	peterz@infradead.org, juri.lelli@redhat.com,
	vincent.guittot@linaro.org, dietmar.eggemann@arm.com,
	rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de,
	vschneid@redhat.com, tgunders@redhat.com,
	david.laight.linux@gmail.com, boqun.feng@gmail.com,
	pbonzini@redhat.com, jfalempe@redhat.com,
	linus.walleij@linaro.org
Subject: Re: [PATCH v15 5/6] rust: time: Add wrapper for fsleep() function
Date: Tue, 29 Apr 2025 15:31:47 +0100	[thread overview]
Message-ID: <aBDi06bQibCIB4En@shell.armlinux.org.uk> (raw)
In-Reply-To: <03ccb65b-a5f8-4afc-84f5-e46f1caf96b0@gmail.com>

On Tue, Apr 29, 2025 at 04:16:01PM +0200, Christian Schrefl wrote:
> On 29.04.25 3:17 PM, FUJITA Tomonori wrote:
> > On Mon, 28 Apr 2025 20:16:47 +0200
> > Andreas Hindborg <a.hindborg@kernel.org> wrote:
> > 
> >> Hi Tomonori,
> >>
> >> "FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:
> >>
> >>> Add a wrapper for fsleep(), flexible sleep functions in
> >>> include/linux/delay.h which typically deals with hardware delays.
> >>>
> >>> The kernel supports several sleep functions to handle various lengths
> >>> of delay. This adds fsleep(), automatically chooses the best sleep
> >>> method based on a duration.
> >>>
> >>> sleep functions including fsleep() belongs to TIMERS, not
> >>> TIMEKEEPING. They are maintained separately. rust/kernel/time.rs is an
> >>> abstraction for TIMEKEEPING. To make Rust abstractions match the C
> >>> side, add rust/kernel/time/delay.rs for this wrapper.
> >>>
> >>> fsleep() can only be used in a nonatomic context. This requirement is
> >>> not checked by these abstractions, but it is intended that klint [1]
> >>> or a similar tool will be used to check it in the future.
> >>
> >> I get an error when building this patch for arm32:
> >>
> >>   + kernel-make -j 96 O=/home/aeh/src/linux-rust/test-build-arm-1.78.0 vmlinux modules
> >>   ld.lld: error: undefined symbol: __aeabi_uldivmod
> >>   >>> referenced by kernel.df165ca450b1fd1-cgu.0
> >>   >>>               rust/kernel.o:(kernel::time::delay::fsleep) in archive vmlinux.a
> >>   >>> did you mean: __aeabi_uidivmod
> >>   >>> defined in: vmlinux.a(arch/arm/lib/lib1funcs.o)
> >>
> >> Looks like a division function of some sort is not defined. Can you
> >> reproduce?
> > 
> > Ah, 64-bit integer division on 32-bit architectures.
> > 
> > I think that the DRM QR driver has the same problem:
> > 
> > https://lore.kernel.org/rust-for-linux/CANiq72ke45eOwckMhWHvmwxc03dxr4rnxxKvx+HvWdBLopZfrQ@mail.gmail.com/
> > 
> > It appears that there is still no consensus on how to resolve it. CC
> > the participants in the above thread.
> 
> From what I remember from the thread is that generally 64 bit divisions
> should be avoided (like the solution for DRM).
> 
> > I think that we can drop this patch and better to focus on Instant and
> > Delta types in this merge window.
> > 
> > With the patch below, this issue could be resolved like the C side,
> > but I'm not sure whether we can reach a consensus quickly.
> 
> I think adding rust bindings for this is fine (and most likely needed),
> for cases where it is required.
> 
> > 
> > diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> > index 48143cdd26b3..c44d45960eb1 100644
> > --- a/rust/helpers/helpers.c
> > +++ b/rust/helpers/helpers.c
> > @@ -19,6 +19,7 @@
> >  #include "io.c"
> >  #include "jump_label.c"
> >  #include "kunit.c"
> > +#include "math64.c"
> >  #include "mutex.c"
> >  #include "page.c"
> >  #include "platform.c"
> > diff --git a/rust/helpers/math64.c b/rust/helpers/math64.c
> > new file mode 100644
> > index 000000000000..f94708cf8fcb
> > --- /dev/null
> > +++ b/rust/helpers/math64.c
> > @@ -0,0 +1,8 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +#include <linux/math64.h>
> > +
> > +s64 rust_helper_div64_s64(s64 dividend, s64 divisor)
> > +{
> > +	return div64_s64(dividend, divisor);
> > +}
> > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> > index de07aadd1ff5..d272e0b0b05d 100644
> > --- a/rust/kernel/lib.rs
> > +++ b/rust/kernel/lib.rs
> > @@ -60,6 +60,7 @@
> >  #[cfg(CONFIG_KUNIT)]
> >  pub mod kunit;
> >  pub mod list;
> > +pub mod math64;
> >  pub mod miscdevice;
> >  #[cfg(CONFIG_NET)]
> >  pub mod net;
> > diff --git a/rust/kernel/math64.rs b/rust/kernel/math64.rs
> > new file mode 100644
> > index 000000000000..523e47911859
> > --- /dev/null
> > +++ b/rust/kernel/math64.rs
> > @@ -0,0 +1,12 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +//! 64-bit integer arithmetic helpers.
> > +//!
> > +//! C header: [`include/linux/math64.h`](srctree/include/linux/math64.h)
> > +
> > +/// Divide a signed 64-bit integer by another signed 64-bit integer.
> > +#[inline]
> > +pub fn div64_s64(dividend: i64, divisor: i64) -> i64 {
> > +    // SAFETY: Calling `div64_s64()` is safe as long as `divisor` is non-zero.
> The safety comment is not valid, nowhere is it guaranteed divisor is non-zero.
> 
> There's three solutions I can think of:
> * Mark this function as `unsafe` and give the responsibility of checking
>   this to the caller,
> * return a `Result` with a division by zero error type or
> * change the type of divisor to `NonZeroI64` [0].
> 
> Probably the best way is to use `NonZeroI64` since that way
> it's statically guaranteed.
> 
> In that case it would also make sense to change `NSEC_PER_USEC` to be `NonZeroI64`.
> 
> 
> Link: https://doc.rust-lang.org/nightly/core/num/type.NonZeroI64.html [0]
> > +    unsafe { bindings::div64_s64(dividend, divisor) }
> 
> Is `s64` just a typedef for `int64_t` and if so this true for every
> architecture? (I don't know the C side very well).
> 
> If not there might need to be some kind of conversion to make sure
> they are passed correctly.
> 
> > +}
> > diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
> > index 863385905029..7b5255893929 100644
> > --- a/rust/kernel/time.rs
> > +++ b/rust/kernel/time.rs
> > @@ -24,6 +24,8 @@
> >  //! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
> >  //! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
> >  
> > +use crate::math64;
> > +
> >  pub mod delay;
> >  pub mod hrtimer;
> >  
> > @@ -229,13 +231,16 @@ pub const fn as_nanos(self) -> i64 {
> >      /// Return the smallest number of microseconds greater than or equal
> >      /// to the value in the [`Delta`].
> >      #[inline]
> > -    pub const fn as_micros_ceil(self) -> i64 {
> > -        self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC
> > +    pub fn as_micros_ceil(self) -> i64 {
> > +        math64::div64_s64(
> It would make sense to change `NSEC_PER_USEC` to be `NonZeroI64`.
> 
> > +            self.as_nanos().saturating_add(NSEC_PER_USEC - 1),
> > +            NSEC_PER_USEC,
> > +        )
> >      }
> >  
> >      /// Return the number of milliseconds in the [`Delta`].
> >      #[inline]
> > -    pub const fn as_millis(self) -> i64 {
> > -        self.as_nanos() / NSEC_PER_MSEC
> > +    pub fn as_millis(self) -> i64 {
> > +        math64::div64_s64(self.as_nanos(), NSEC_PER_MSEC)

There is no way this should ever be an expensive 64-bit by 64-bit
division. Think about value of the divisor here - there's 1000us
in 1ms, and 1000ns in 1us, so this has the value of 1000000,
which is 20 bits.

So for a 32-bit architecture, trying to do a 64-bit by 64-bit
division is expensive, and 32-bit architectures don't implement
this as a general rule because of this - most times you do not
have a 64-bit divisor, but something much smaller, making a
64-bit by 32-bit division more suitable. That is a lot faster on
32-bit architectures.

So, I think more thought is needed to be put into this by Rust
folk, rather than blindly forcing everything to be 64-bit by
64-bit even when the divisor is 20-bit.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

  reply	other threads:[~2025-04-29 14:32 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-23 19:28 [PATCH v15 0/6] rust: Add IO polling FUJITA Tomonori
2025-04-23 19:28 ` [PATCH v15 1/6] rust: hrtimer: Add Ktime temporarily FUJITA Tomonori
2025-04-23 19:28 ` [PATCH v15 2/6] rust: time: Add PartialEq/Eq/PartialOrd/Ord trait to Ktime FUJITA Tomonori
2025-04-23 19:28 ` [PATCH v15 3/6] rust: time: Introduce Delta type FUJITA Tomonori
2025-04-23 19:28 ` [PATCH v15 4/6] rust: time: Introduce Instant type FUJITA Tomonori
2025-04-23 19:28 ` [PATCH v15 5/6] rust: time: Add wrapper for fsleep() function FUJITA Tomonori
2025-04-28 18:16   ` Andreas Hindborg
2025-04-29 13:17     ` FUJITA Tomonori
2025-04-29 14:16       ` Christian Schrefl
2025-04-29 14:31         ` Russell King (Oracle) [this message]
2025-04-29 14:35       ` Miguel Ojeda
2025-04-30 13:51         ` FUJITA Tomonori
2025-04-30 14:50           ` Boqun Feng
2025-04-30 16:43           ` Christian Schrefl
2025-04-29 15:51       ` Arnd Bergmann
2025-04-29 16:03         ` Boqun Feng
2025-04-29 16:11           ` Arnd Bergmann
2025-04-29 17:15             ` Boqun Feng
2025-04-29 18:33               ` Arnd Bergmann
2025-04-29 19:14                 ` Boqun Feng
2025-04-29 19:27                   ` Boqun Feng
2025-04-23 19:28 ` [PATCH v15 6/6] MAINTAINERS: rust: Add a new section for all of the time stuff FUJITA Tomonori
2025-04-30 10:40 ` [PATCH v15 0/6] rust: Add IO polling Andreas Hindborg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aBDi06bQibCIB4En@shell.armlinux.org.uk \
    --to=linux@armlinux.org.uk \
    --cc=a.hindborg@kernel.org \
    --cc=a.hindborg@samsung.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=andrew@lunn.ch \
    --cc=anna-maria@linutronix.de \
    --cc=arnd@arndb.de \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=bsegall@google.com \
    --cc=chrisi.schrefl@gmail.com \
    --cc=daniel.almeida@collabora.com \
    --cc=david.laight.linux@gmail.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=frederic@kernel.org \
    --cc=fujita.tomonori@gmail.com \
    --cc=gary@garyguo.net \
    --cc=hkallweit1@gmail.com \
    --cc=jfalempe@redhat.com \
    --cc=jstultz@google.com \
    --cc=juri.lelli@redhat.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=me@kloenk.dev \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=sboyd@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=tgunders@redhat.com \
    --cc=tmgross@umich.edu \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).