From: Boqun Feng <boqun.feng@gmail.com>
To: Dirk Behme <dirk.behme@de.bosch.com>
Cc: "Lyude Paul" <lyude@redhat.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
"Danilo Krummrich" <dakr@redhat.com>,
airlied@redhat.com, "Ingo Molnar" <mingo@redhat.com>,
"Will Deacon" <will@kernel.org>,
"Waiman Long" <longman@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@samsung.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
"Aakash Sen Sharma" <aakashsensharma@gmail.com>,
"Valentin Obst" <kernel@valentinobst.de>
Subject: Re: [PATCH v3 1/3] rust: Introduce irq module
Date: Mon, 26 Aug 2024 07:21:47 -0700 [thread overview]
Message-ID: <ZsyPezklN_tANFtQ@boqun-archlinux> (raw)
In-Reply-To: <3f6a5c86-8dc4-4a62-8308-5ca25f9e4aec@de.bosch.com>
On Mon, Aug 26, 2024 at 01:21:17PM +0200, Dirk Behme wrote:
> Hi Lyude,
>
> On 02.08.2024 02:10, Lyude Paul wrote:
> > This introduces a module for dealing with interrupt-disabled contexts,
> > including the ability to enable and disable interrupts
> > (with_irqs_disabled()) - along with the ability to annotate functions as
> > expecting that IRQs are already disabled on the local CPU.
> >
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> ...
> > diff --git a/rust/kernel/irq.rs b/rust/kernel/irq.rs
> > new file mode 100644
> > index 0000000000000..b52f8073e5cd0
> > --- /dev/null
> > +++ b/rust/kernel/irq.rs
> > @@ -0,0 +1,84 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +//! Interrupt controls
> > +//!
> > +//! This module allows Rust code to control processor interrupts. [`with_irqs_disabled()`] may be
> > +//! used for nested disables of interrupts, whereas [`IrqDisabled`] can be used for annotating code
> > +//! that requires interrupts to be disabled.
> > +
> > +use bindings;
> > +use core::marker::*;
> > +
> > +/// A token that is only available in contexts where IRQs are disabled.
> > +///
> > +/// [`IrqDisabled`] is marker made available when interrupts are not active. Certain functions take
> > +/// an [`IrqDisabled`] in order to indicate that they may only be run in IRQ-free contexts.
> > +///
> > +/// This is a marker type; it has no size, and is simply used as a compile-time guarantee that
> > +/// interrupts are disabled where required.
> > +///
> > +/// This token can be created by [`with_irqs_disabled`]. See [`with_irqs_disabled`] for examples and
> > +/// further information.
> > +#[derive(Copy, Clone, Debug, Ord, Eq, PartialOrd, PartialEq, Hash)]
> > +pub struct IrqDisabled<'a>(PhantomData<(&'a (), *mut ())>);
> > +
> > +impl IrqDisabled<'_> {
> > + /// Create a new [`IrqDisabled`] without disabling interrupts.
> > + ///
> > + /// This creates an [`IrqDisabled`] token, which can be passed to functions that must be run
> > + /// without interrupts. If debug assertions are enabled, this function will assert that
> > + /// interrupts are disabled upon creation. Otherwise, it has no size or cost at runtime.
> > + ///
> > + /// # Panics
> > + ///
> > + /// If debug assertions are enabled, this function will panic if interrupts are not disabled
> > + /// upon creation.
> > + ///
> > + /// # Safety
> > + ///
> > + /// This function must only be called in contexts where it is already known that interrupts have
> > + /// been disabled for the current CPU, as the user is making a promise that they will remain
> > + /// disabled at least until this [`IrqDisabled`] is dropped.
> > + pub unsafe fn new() -> Self {
> > + // SAFETY: FFI call with no special requirements
> > + debug_assert!(unsafe { bindings::irqs_disabled() });
> > +
> > + Self(PhantomData)
> > + }
> > +}
>
> I have some (understanding) questions for this IrqDisabled::new():
>
> 1. It looks to me that both examples, below in this file irq.rs nor the
> with_irqs_disabled() example in spinlock.rs in the 3rd patch seem to use
> IrqDisabled::new()? At least some debug pr_info() added here doesn't print
> anything.
>
> What's the intended use case of IrqDisabled::new()? Do we have any example?
>
> I 'simulated' an interrupt handler where we know the interrupts are
> disabled:
>
> let flags = unsafe { bindings::local_irq_save() }; // Simulate IRQ disable
> of an interrupt handler
> let mut g = foo.lock_with(unsafe {IrqDisabled::new() });
> g.val = 42;
> unsafe { bindings::local_irq_restore(flags) }; // Simulate IRQ re-enable of
> an interrupt handler
>
> Is this the intended use case?
>
>
> 2. If the example above is what is intended here, is it intended that this
> has to be called unsafe{}?
>
> foo.lock_with(unsafe {IrqDisabled::new() });
>
>
> 3. I somehow feel slightly uncomfortable with the debug_assert!().
>
> I understood that this is intended to be not in production code and only
> enabled with RUST_DEBUG_ASSERTIONS for performance reasons? But I have some
> doubts how many people have RUST_DEBUG_ASSERTIONS enabled? And disable it
> for the production build?
>
> Wouldn't it be better to be on the safe side and have this check, always?
No, for example in your code example above, the IRQ is known being
disabled, so actually there's no point to check. The checking of course
makes sense in a function where there is no IRQ disable code, and you
want to make sure it's only called when IRQ disabled. But that's
something you want to make sure at development time rather than in the
production.
> Wouldn't a permanent if statement checking this be safer for all cases?
I don't think so, it's just a checking, even if we enable this in the
production, the best it could do is just telling us the code is
incorrect. If one realy wants to make sure a function works in both IRQ
disabled and enabled cases, he/she should check the irq status and
handle it accordingly e.g.
if (irqs_disabled()) {
// irq is disabled, we can call it directly
do_sth();
} else {
// Disable IRQ on our own.
local_irq_disable();
do_sth();
local_irq_enabled();
}
> Compare e.g. BUG_ON() or WARN_ONCE() or similar in the kernel's C code?
>
> Or could we invent anything more clever?
>
I'm open to any new idea, but for the time being, I think the
debug_assert!() makes more sense.
Regards,
Boqun
>
[...]
next prev parent reply other threads:[~2024-08-26 14:22 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-02 0:09 [PATCH v3 0/3] rust: Add irq abstraction, SpinLockIrq Lyude Paul
2024-08-02 0:10 ` [PATCH v3 1/3] rust: Introduce irq module Lyude Paul
2024-08-14 17:10 ` Boqun Feng
2024-08-14 17:35 ` Boqun Feng
2024-08-14 19:38 ` Lyude Paul
2024-08-14 20:17 ` Boqun Feng
2024-08-14 20:44 ` Benno Lossin
2024-08-14 20:57 ` Boqun Feng
2024-08-15 4:53 ` Boqun Feng
2024-08-15 6:40 ` Benno Lossin
2024-08-15 16:02 ` Boqun Feng
2024-08-15 21:05 ` Lyude Paul
2024-08-15 21:31 ` Lyude Paul
2024-08-15 21:46 ` Benno Lossin
2024-08-15 22:13 ` Lyude Paul
2024-08-16 15:28 ` Boqun Feng
2024-08-15 21:41 ` Benno Lossin
2024-08-15 21:43 ` Lyude Paul
2024-08-15 20:31 ` Lyude Paul
2024-08-15 21:48 ` Benno Lossin
2024-08-26 11:21 ` Dirk Behme
2024-08-26 14:21 ` Boqun Feng [this message]
2024-08-26 14:59 ` Dirk Behme
2024-08-26 15:34 ` Boqun Feng
2024-08-02 0:10 ` [PATCH v3 2/3] rust: sync: Introduce lock::Backend::Context Lyude Paul
2024-08-20 10:26 ` Dirk Behme
2024-08-02 0:10 ` [PATCH v3 3/3] rust: sync: Add SpinLockIrq Lyude Paul
2024-08-13 20:26 ` [PATCH v3 0/3] rust: Add irq abstraction, SpinLockIrq Lyude Paul
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=ZsyPezklN_tANFtQ@boqun-archlinux \
--to=boqun.feng@gmail.com \
--cc=a.hindborg@samsung.com \
--cc=aakashsensharma@gmail.com \
--cc=airlied@redhat.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=dakr@redhat.com \
--cc=dirk.behme@de.bosch.com \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=kernel@valentinobst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=lyude@redhat.com \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
--cc=will@kernel.org \
/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).