* [PATCH v3 0/3] rust: Add pr_*_once macros
@ 2024-11-09 20:30 Jens Korinth via B4 Relay
2024-11-09 20:30 ` [PATCH v3 1/3] rust: print: Add do_once_lite macro Jens Korinth via B4 Relay
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Jens Korinth via B4 Relay @ 2024-11-09 20:30 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross
Cc: rust-for-linux, FUJITA Tomonori, Dirk Behme, Jens Korinth
Add Rust version of pr_[emerg|alert|crit|err|warn|notic|info]_once
functions, which print a message only once.
v3:
- Fix rustdoc error, formatting issues
- Fix missing Signed-off-by
v2: https://lore.kernel.org/r/20241107-pr_once_macros-v2-0-dc0317ff301e@tuta.io
- Split patch into do_once_lite part and pr_*_once macros
- Add macro rule for call without condition => renamed to do_once_lite
- Used condition-less call in pr_*_once macros
- Added examples
- Removed TODO in kernel/error.rs using pr_warn_once
v1: https://lore.kernel.org/rust-for-linux/20241106.083113.356536037967804464.fujita.tomonori@gmail.com/
Co-developed-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Jens Korinth <jens.korinth@tuta.io>
---
FUJITA Tomonori (1):
rust: print: Add pr_*_once macros
Jens Korinth (2):
rust: print: Add do_once_lite macro
rust: error: Replace pr_warn by pr_warn_once
rust/kernel/error.rs | 3 +-
rust/kernel/print.rs | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 161 insertions(+), 2 deletions(-)
---
base-commit: ae7851c29747fa3765ecb722fe722117a346f988
change-id: 20241107-pr_once_macros-6438e6f5b923
Best regards,
--
Jens Korinth <jens.korinth@tuta.io>
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 20:30 [PATCH v3 0/3] rust: Add pr_*_once macros Jens Korinth via B4 Relay @ 2024-11-09 20:30 ` Jens Korinth via B4 Relay 2024-11-09 20:41 ` Miguel Ojeda 2024-11-09 22:56 ` Boqun Feng 2024-11-09 20:30 ` [PATCH v3 2/3] rust: print: Add pr_*_once macros Jens Korinth via B4 Relay ` (2 subsequent siblings) 3 siblings, 2 replies; 15+ messages in thread From: Jens Korinth via B4 Relay @ 2024-11-09 20:30 UTC (permalink / raw) To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross Cc: rust-for-linux, FUJITA Tomonori, Dirk Behme, Jens Korinth From: Jens Korinth <jens.korinth@tuta.io> Add do_once_lite macro that executes code only once. Has two rules, one with a condition to replace [`do_once_lite_if`] in the kernel, and one without. Signed-off-by: Jens Korinth <jens.korinth@tuta.io> --- rust/kernel/print.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs index a28077a7cb301193dcca293befb096b2dd153202..9c7434b221984ad325138e5dc90ab4340cd0be2e 100644 --- a/rust/kernel/print.rs +++ b/rust/kernel/print.rs @@ -414,3 +414,37 @@ macro_rules! pr_cont ( $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*) ) ); + +/// Executes code only once. +/// +/// Equivalent to the kernel's [`do_once_lite_if`] macro when called with +/// a condition expression. +/// Public but hidden since it should only be used from public macros. +/// +/// # Examples +/// +/// ``` +/// kernel::do_once_lite!(pr_warn!("warn once")); +/// kernel::do_once_lite!({ /* perform_complex_test() */ true }, pr_warn!("warn only once")); +/// ``` +#[doc(hidden)] +#[macro_export] +macro_rules! do_once_lite ( + ($e:expr) => ( + $crate::do_once_lite!(true, $e); + ); + ($condition:expr, $e:expr) => ( + { + #[link_section = ".data.once"] + static ALREADY_DONE: core::sync::atomic::AtomicBool = + core::sync::atomic::AtomicBool::new(false); + + if !ALREADY_DONE.load(core::sync::atomic::Ordering::Relaxed) + && $condition + && !ALREADY_DONE.swap(true, core::sync::atomic::Ordering::Relaxed) + { + $e; + } + } + ); +); -- 2.44.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 20:30 ` [PATCH v3 1/3] rust: print: Add do_once_lite macro Jens Korinth via B4 Relay @ 2024-11-09 20:41 ` Miguel Ojeda 2024-11-09 21:33 ` jens.korinth 2024-11-09 22:56 ` Boqun Feng 1 sibling, 1 reply; 15+ messages in thread From: Miguel Ojeda @ 2024-11-09 20:41 UTC (permalink / raw) To: jens.korinth Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, rust-for-linux, FUJITA Tomonori, Dirk Behme On Sat, Nov 9, 2024 at 9:30 PM Jens Korinth via B4 Relay <devnull+jens.korinth.tuta.io@kernel.org> wrote: > > Add do_once_lite macro that executes code only once. > Has two rules, one with a condition to replace [`do_once_lite_if`] in > the kernel, and one without. It is fine using Markdown in commit messages (personally, I think it is nice for Rust-related commits), but if you do so, please use it consistently (e.g. backticks on the first line: "Add do_once_lite macro..."). In addition, the intra-doc link does not really work in commit messages :) You probably want to either remove the link, or use an actual Link: tag, e.g. ...to replace `do_once_lite_if` [0] in... ... Link: https://... [0] > +/// Equivalent to the kernel's [`do_once_lite_if`] macro when called with > +/// a condition expression. > +/// Public but hidden since it should only be used from public macros. Paragraphs should have an empty line between them. It does not matter much if the docs are not generated, but still, we should try to write them correctly even then. > +/// ``` > +/// kernel::do_once_lite!(pr_warn!("warn once")); > +/// kernel::do_once_lite!({ /* perform_complex_test() */ true }, pr_warn!("warn only once")); > +/// ``` Since we will have `pr_warn_once!` for this, could we perhaps come up with another example? i.e. to avoid users thinking that they should use it this way. Also, you could use `assert*!` (possibly hidden, depending on what you want the user to see) since it doubles as a test. > +#[doc(hidden)] Do we want it to be hidden? I guess this could be useful for other abstractions etc. In addition, if we unhide it, should we move it into its own file? Just like C has `once_lite.h` etc. Thanks! Cheers, Miguel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 20:41 ` Miguel Ojeda @ 2024-11-09 21:33 ` jens.korinth 2024-11-09 21:44 ` Miguel Ojeda 0 siblings, 1 reply; 15+ messages in thread From: jens.korinth @ 2024-11-09 21:33 UTC (permalink / raw) To: Miguel Ojeda Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme > In addition, the intra-doc link does not really work in commit > messages :) You probably want to either remove the link, or use an > actual Link: tag, e.g. > > ...to replace `do_once_lite_if` [0] in... > ... > Link: https://... [0] > Yes, you're right, I also just noticed that the C macro is of course called `DO_ONCE_LITE_IF`. Will fix this and the rustdoc issues in the next revision. > Since we will have `pr_warn_once!` for this, could we perhaps come up > with another example? i.e. to avoid users thinking that they should > use it this way. > > Also, you could use `assert*!` (possibly hidden, depending on what you > want the user to see) since it doubles as a test. > There aren't many other uses of `DO_ONCE_LITE_IF` in the kernel, that's why I kept it in `print.rs` and hidden. I didn't quite understand what you meant with `assert*!` - can you give me an example? >> +#[doc(hidden)] >> > > Do we want it to be hidden? I guess this could be useful for other > abstractions etc. > > In addition, if we unhide it, should we move it into its own file? > Just like C has `once_lite.h` etc. > Good point, but I'd only do that if it has at least one other use from somewhere else. I was considering to implement `WARN_*_ONCE`, the C implementations also use `DO_ONCE_LITE_IF`? But as far as I can tellthere is no implementation of `WARN`, or `__WARN_printf` yet and that won't be trivial. Jens ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 21:33 ` jens.korinth @ 2024-11-09 21:44 ` Miguel Ojeda 0 siblings, 0 replies; 15+ messages in thread From: Miguel Ojeda @ 2024-11-09 21:44 UTC (permalink / raw) To: jens.korinth Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme On Sat, Nov 9, 2024 at 10:33 PM <jens.korinth@tuta.io> wrote: > > There aren't many other uses of `DO_ONCE_LITE_IF` in the kernel, that's > why I kept it in `print.rs` and hidden. I didn't quite understand what you > meant with `assert*!` - can you give me an example? Like in userspace Rust, our examples are run as tests (but unlike userspace, we transform them into KUnit tests so that they run in that framework): https://docs.kernel.org/rust/testing.html#the-kunit-tests So examples double as tests, and thus if you use `assert!`, you can check for things that you expect to be true or not (e.g. that something has run, or that it has run once, etc.). The `assert!`s are passed back into KUnit. > Good point, but I'd only do that if it has at least one other use from I would still put it in its own file, even with a single user, since it really is a distinct facility than printing that is likely to be used elsewhere (i.e. it is not just an implementation detail very tied to the printing macros only). The C side also does it, so there is even more reason to do so. (It also allows you to reference the C header(s) in the new file/module.) In general, if we expect that we will be moving something, then we should try to put it in the right place directly: moving things later is more painful, especially considering the different trees that carry patches and backports. Thanks! Cheers, Miguel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 20:30 ` [PATCH v3 1/3] rust: print: Add do_once_lite macro Jens Korinth via B4 Relay 2024-11-09 20:41 ` Miguel Ojeda @ 2024-11-09 22:56 ` Boqun Feng 2024-11-10 7:45 ` jens.korinth 2024-11-11 9:17 ` Alice Ryhl 1 sibling, 2 replies; 15+ messages in thread From: Boqun Feng @ 2024-11-09 22:56 UTC (permalink / raw) To: jens.korinth Cc: Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, rust-for-linux, FUJITA Tomonori, Dirk Behme Hi Jens, Thanks for working on this! On Sat, Nov 09, 2024 at 09:30:07PM +0100, Jens Korinth via B4 Relay wrote: > From: Jens Korinth <jens.korinth@tuta.io> > > Add do_once_lite macro that executes code only once. > Has two rules, one with a condition to replace [`do_once_lite_if`] in > the kernel, and one without. > Instead of a do_once_lite macro, I suggest that we implement a `Once` type similar to the std one [1]. "Doing something once" doesn't need to be implemented as a macro or relying the static memory allocation. I've checked the usage of section ".data.once", it's only used for reset WARN_*ONCE() state (see clear_warn_once_set()), so we can have an `Once` implementation, and mark it as `.data.once` link section in `pr_*_once!()` like: macro_rules! pr_warn_once ( ($($arg:tt)*) => {{ #[link_section = ".data.once"] static ONCE: Once = Once::new(); ONCE.call_once(|| { $crate::pr_warn!($($arg)*) }); }} ); With this `Once` type, we can do other things like waiting for some initialization to finish. We can put the waiting as a future work, since `pr_*_once!()` don't need it. Thoughts? Another meta comment is the usage of `AtomicBool`, please see the LKMM atomic patchset [2]. In short, we won't use core::sync atomics in kernel, instead we can only use the atomics implemented by ourselves. And we currently don't support `Atomic<u8>`, there requires some work to get that done. The other thing of using `AtomicBool` is that it's not the most space-efficient way for `Once` (if xchg() is used) on all the archs that support Rust in kernel. RISCV doesn't has a byte-wise swap, so the implementation has to simulate with a 32-bit or 64-bit swap + mask, that'll be totally 5 instructions, and each instruction take 4 bytes. As a result, if the `swap()` is inlined (which most atomic operations would be for performance reasons), you save 3 bytes by using `AtomicBool` other than `AtomicI32` at data section, but you pay 4*4 extra bytes at the instruction section compared to using `AtomicI32`. The solution could be: 1) forcing the `swap()` to be a outline function call, or 2) using i32 insteal of bool for `Once` on RISCV. Either way, I would like to see this being taken care of, and you could share some results of the space cost from the solution you finally use. Thanks! [1]: https://doc.rust-lang.org/std/sync/struct.Once.html# [2]: https://lore.kernel.org/rust-for-linux/20241101060237.1185533-1-boqun.feng@gmail.com/ Regards, Boqun > Signed-off-by: Jens Korinth <jens.korinth@tuta.io> > --- > rust/kernel/print.rs | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs > index a28077a7cb301193dcca293befb096b2dd153202..9c7434b221984ad325138e5dc90ab4340cd0be2e 100644 > --- a/rust/kernel/print.rs > +++ b/rust/kernel/print.rs > @@ -414,3 +414,37 @@ macro_rules! pr_cont ( > $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*) > ) > ); > + > +/// Executes code only once. > +/// > +/// Equivalent to the kernel's [`do_once_lite_if`] macro when called with > +/// a condition expression. > +/// Public but hidden since it should only be used from public macros. > +/// > +/// # Examples > +/// > +/// ``` > +/// kernel::do_once_lite!(pr_warn!("warn once")); > +/// kernel::do_once_lite!({ /* perform_complex_test() */ true }, pr_warn!("warn only once")); > +/// ``` > +#[doc(hidden)] > +#[macro_export] > +macro_rules! do_once_lite ( > + ($e:expr) => ( > + $crate::do_once_lite!(true, $e); > + ); > + ($condition:expr, $e:expr) => ( > + { > + #[link_section = ".data.once"] > + static ALREADY_DONE: core::sync::atomic::AtomicBool = > + core::sync::atomic::AtomicBool::new(false); > + > + if !ALREADY_DONE.load(core::sync::atomic::Ordering::Relaxed) > + && $condition > + && !ALREADY_DONE.swap(true, core::sync::atomic::Ordering::Relaxed) > + { > + $e; > + } > + } > + ); > +); > > -- > 2.44.1 > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 22:56 ` Boqun Feng @ 2024-11-10 7:45 ` jens.korinth 2024-11-10 19:23 ` Boqun Feng 2024-11-11 9:17 ` Alice Ryhl 1 sibling, 1 reply; 15+ messages in thread From: jens.korinth @ 2024-11-10 7:45 UTC (permalink / raw) To: Boqun Feng Cc: Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme > With this `Once` type, we can do other things like waiting for some > initialization to finish. We can put the waiting as a future work, since > `pr_*_once!()` don't need it. > > Thoughts? > A `Once` implementation as the general approach of doing things once in the kernel would make a lot of sense to me and I think it would be the"rusty" way to go. I'd prefer that to `do_once_lite`, for sure. However, I'm not sure if it can replace `do_once_lite`. Doesn't `Once` use a closure? I may be mistaken, but wouldn't that have at least the size of afunction pointer? My second concern would be with the methods of `Once` itself: We would have to rely on link-time optimization to inline the methods, which may bedeactivated. If they are not inlined, it could mean a far-jump on a potential hot-path that could be triggered many times per second? > Another meta comment is the usage of `AtomicBool`, please see the LKMM > atomic patchset [2]. In short, we won't use core::sync atomics in > kernel, instead we can only use the atomics implemented by ourselves. > And we currently don't support `Atomic<u8>`, there requires some work to > get that done. > Ouch, I didn't know that. Sounds like an interesting topic! I would like to understand in more detail how the Rust part will imitate the inline assembly approaches of the arch-specific code in C. So far my mental model of that is "we'll wrap it with bindgen". ;) > The other thing of using `AtomicBool` is that it's not the most > space-efficient way for `Once` (if xchg() is used) on all the archs that > support Rust in kernel. RISCV doesn't has a byte-wise swap, so the > implementation has to simulate with a 32-bit or 64-bit swap + mask, > that'll be totally 5 instructions, and each instruction take 4 bytes. As > a result, if the `swap()` is inlined (which most atomic operations would > be for performance reasons), you save 3 bytes by using `AtomicBool` > other than `AtomicI32` at data section, but you pay 4*4 extra bytes at > the instruction section compared to using `AtomicI32`. > Ok, wow, good point and explanation! But it does sound like an (arch-specific) implementation detail. I would expect the `AtomicBool` implementation to do the "smart" thing on every arch, no? I think on thesemantic level we want an `AtomicBool` here, regardless of how it is implemented on RISCV, or another arch? Jens ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-10 7:45 ` jens.korinth @ 2024-11-10 19:23 ` Boqun Feng 0 siblings, 0 replies; 15+ messages in thread From: Boqun Feng @ 2024-11-10 19:23 UTC (permalink / raw) To: jens.korinth Cc: Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme On Sun, Nov 10, 2024 at 08:45:49AM +0100, jens.korinth@tuta.io wrote: > > > > With this `Once` type, we can do other things like waiting for some > > initialization to finish. We can put the waiting as a future work, since > > `pr_*_once!()` don't need it. > > > > Thoughts? > > > A `Once` implementation as the general approach of doing things once in > the kernel would make a lot of sense to me and I think it would be the"rusty" way to go. I'd prefer that to `do_once_lite`, for sure. > > However, I'm not sure if it can replace `do_once_lite`. Doesn't `Once` use > a closure? I may be mistaken, but wouldn't that have at least the size of afunction pointer? > No, because `Once` doesn't store the closure, it's just a atomic flag to ensure that Once::call_once() can only execute once, as a result if you have two threads calling the `call_once()` function in the same time, only one will win, and the other won't get executed. It's something like: https://godbolt.org/z/6PaWxnWxd > My second concern would be with the methods of `Once` itself: We would > have to rely on link-time optimization to inline the methods, which may bedeactivated. If they are not inlined, it could mean a far-jump on a potential I don't think LTO is the one who inlines the methods, normal compiler optimization could do the work, hint: `call_once()` is a generic function over the closure. > hot-path that could be triggered many times per second? > and normally kernel will be compiled with -Copt-level=2, and the compiler would "inline" the closures properly. > > Another meta comment is the usage of `AtomicBool`, please see the LKMM > > atomic patchset [2]. In short, we won't use core::sync atomics in > > kernel, instead we can only use the atomics implemented by ourselves. > > And we currently don't support `Atomic<u8>`, there requires some work to > > get that done. > > > Ouch, I didn't know that. Sounds like an interesting topic! I would like to > understand in more detail how the Rust part will imitate the inline assembly > approaches of the arch-specific code in C. So far my mental model of that is > "we'll wrap it with bindgen". ;) > Feel free to review that patchset! ;-) > > The other thing of using `AtomicBool` is that it's not the most > > space-efficient way for `Once` (if xchg() is used) on all the archs that > > support Rust in kernel. RISCV doesn't has a byte-wise swap, so the > > implementation has to simulate with a 32-bit or 64-bit swap + mask, > > that'll be totally 5 instructions, and each instruction take 4 bytes. As > > a result, if the `swap()` is inlined (which most atomic operations would > > be for performance reasons), you save 3 bytes by using `AtomicBool` > > other than `AtomicI32` at data section, but you pay 4*4 extra bytes at > > the instruction section compared to using `AtomicI32`. > > > Ok, wow, good point and explanation! But it does sound like an > (arch-specific) implementation detail. I would expect the `AtomicBool` > implementation to do the "smart" thing on every arch, no? I think on thesemantic level we want an `AtomicBool` here, regardless of how it is > implemented on RISCV, or another arch? The thing is `AtomicBool` is not the right layer for this, because it has to be the same represention as a normal bool [1]. `Once` seems to be a good layer to do it. [1]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html Regards, Boqun Regards, Boqun > Jens ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-09 22:56 ` Boqun Feng 2024-11-10 7:45 ` jens.korinth @ 2024-11-11 9:17 ` Alice Ryhl 2024-11-11 13:34 ` jens.korinth 1 sibling, 1 reply; 15+ messages in thread From: Alice Ryhl @ 2024-11-11 9:17 UTC (permalink / raw) To: Boqun Feng Cc: jens.korinth, Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, rust-for-linux, FUJITA Tomonori, Dirk Behme On Sat, Nov 9, 2024 at 11:56 PM Boqun Feng <boqun.feng@gmail.com> wrote: > > Hi Jens, > > Thanks for working on this! > > On Sat, Nov 09, 2024 at 09:30:07PM +0100, Jens Korinth via B4 Relay wrote: > > From: Jens Korinth <jens.korinth@tuta.io> > > > > Add do_once_lite macro that executes code only once. > > Has two rules, one with a condition to replace [`do_once_lite_if`] in > > the kernel, and one without. > > > > Instead of a do_once_lite macro, I suggest that we implement a `Once` > type similar to the std one [1]. "Doing something once" doesn't need to > be implemented as a macro or relying the static memory allocation. I've > checked the usage of section ".data.once", it's only used for reset > WARN_*ONCE() state (see clear_warn_once_set()), so we can have an `Once` > implementation, and mark it as `.data.once` link section in > `pr_*_once!()` like: > > macro_rules! pr_warn_once ( > ($($arg:tt)*) => {{ > #[link_section = ".data.once"] > static ONCE: Once = Once::new(); > > ONCE.call_once(|| { $crate::pr_warn!($($arg)*) }); > }} > ); > > With this `Once` type, we can do other things like waiting for some > initialization to finish. We can put the waiting as a future work, since > `pr_*_once!()` don't need it. > > Thoughts? Using a Once type for this seems like a good idea to me. Of course it requires that Once has the right memory representation so that putting it in .data.once is valid, but that doesn't seem like a big issue. > Another meta comment is the usage of `AtomicBool`, please see the LKMM > atomic patchset [2]. In short, we won't use core::sync atomics in > kernel, instead we can only use the atomics implemented by ourselves. > And we currently don't support `Atomic<u8>`, there requires some work to > get that done. > > The other thing of using `AtomicBool` is that it's not the most > space-efficient way for `Once` (if xchg() is used) on all the archs that > support Rust in kernel. RISCV doesn't has a byte-wise swap, so the > implementation has to simulate with a 32-bit or 64-bit swap + mask, > that'll be totally 5 instructions, and each instruction take 4 bytes. As > a result, if the `swap()` is inlined (which most atomic operations would > be for performance reasons), you save 3 bytes by using `AtomicBool` > other than `AtomicI32` at data section, but you pay 4*4 extra bytes at > the instruction section compared to using `AtomicI32`. > > The solution could be: 1) forcing the `swap()` to be a outline function > call, or 2) using i32 insteal of bool for `Once` on RISCV. Either way, > I would like to see this being taken care of, and you could share some > results of the space cost from the solution you finally use. Thanks! One advantage of using a Once type is that we can use core::sync::atomic until we have working LKMM atomics and then we just swap out the Once type without having to modify the warn_once abstractions. Alice ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-11 9:17 ` Alice Ryhl @ 2024-11-11 13:34 ` jens.korinth 2024-11-11 13:53 ` Alice Ryhl 0 siblings, 1 reply; 15+ messages in thread From: jens.korinth @ 2024-11-11 13:34 UTC (permalink / raw) To: Alice Ryhl Cc: Boqun Feng, Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme > One advantage of using a Once type is that we can use > core::sync::atomic until we have working LKMM atomics and then we just > swap out the Once type without having to modify the warn_once > abstractions. > Ok, that's a really good argument. I'm a bit perplexed why the generic `Atomic` type has such requirements, they seem unrelated to the semantics of the interface. But since it is defined that way, `Once`, or `OnceLock` etc., seem the way to go. Question is: Would you still merge the pr_*_once macros with the`do_once_lite` hidden in `print.rs` for now? Or would you rather wait until the `Once` abstraction is available? Jens ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-11 13:34 ` jens.korinth @ 2024-11-11 13:53 ` Alice Ryhl 2024-11-11 17:46 ` Boqun Feng 0 siblings, 1 reply; 15+ messages in thread From: Alice Ryhl @ 2024-11-11 13:53 UTC (permalink / raw) To: jens.korinth Cc: Boqun Feng, Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme On Mon, Nov 11, 2024 at 2:34 PM <jens.korinth@tuta.io> wrote: > > > One advantage of using a Once type is that we can use > > core::sync::atomic until we have working LKMM atomics and then we just > > swap out the Once type without having to modify the warn_once > > abstractions. > > > Ok, that's a really good argument. I'm a bit perplexed why the generic > `Atomic` type has such requirements, they seem unrelated to the semantics > of the interface. But since it is defined that way, `Once`, or `OnceLock` etc., > seem the way to go. > > Question is: Would you still merge the pr_*_once macros with the`do_once_lite` hidden in `print.rs` for now? Or would you rather wait until > the `Once` abstraction is available? I just realized a significant issue with this plan: The standard library type called Once is implemented such that the calls that lose the race will *block* until the closure finishes. That's not what we want here, and it's also not what Boqun's godbolt does. We should not add types with identical APIs and names as the stdlib type if we don't match the API. Alice ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/3] rust: print: Add do_once_lite macro 2024-11-11 13:53 ` Alice Ryhl @ 2024-11-11 17:46 ` Boqun Feng 0 siblings, 0 replies; 15+ messages in thread From: Boqun Feng @ 2024-11-11 17:46 UTC (permalink / raw) To: Alice Ryhl Cc: jens.korinth, Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, Rust For Linux, FUJITA Tomonori, Dirk Behme On Mon, Nov 11, 2024 at 02:53:23PM +0100, Alice Ryhl wrote: > On Mon, Nov 11, 2024 at 2:34 PM <jens.korinth@tuta.io> wrote: > > > > > One advantage of using a Once type is that we can use > > > core::sync::atomic until we have working LKMM atomics and then we just > > > swap out the Once type without having to modify the warn_once > > > abstractions. > > > Yeah, although I'd rather we merge the LKMM atomics ASAP, and we can avoid the switching as much as possible ;-) > > Ok, that's a really good argument. I'm a bit perplexed why the generic > > `Atomic` type has such requirements, they seem unrelated to the semantics > > of the interface. But since it is defined that way, `Once`, or `OnceLock` etc., > > seem the way to go. > > > > Question is: Would you still merge the pr_*_once macros with the`do_once_lite` hidden in `print.rs` for now? Or would you rather wait until > > the `Once` abstraction is available? > > I just realized a significant issue with this plan: The standard > library type called Once is implemented such that the calls that lose > the race will *block* until the closure finishes. That's not what we > want here, and it's also not what Boqun's godbolt does. We should not > add types with identical APIs and names as the stdlib type if we don't > match the API. > Thanks for bringing this up, for this particular one, we can call it `OnceLite`, it also matches the C side name. `OnceLite` doesn't care about when the `call_once()` is finished, it only cares about doing something for exactly once. Make sense? Regards, Boqun > Alice ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3 2/3] rust: print: Add pr_*_once macros 2024-11-09 20:30 [PATCH v3 0/3] rust: Add pr_*_once macros Jens Korinth via B4 Relay 2024-11-09 20:30 ` [PATCH v3 1/3] rust: print: Add do_once_lite macro Jens Korinth via B4 Relay @ 2024-11-09 20:30 ` Jens Korinth via B4 Relay 2024-11-09 20:30 ` [PATCH v3 3/3] rust: error: Replace pr_warn by pr_warn_once Jens Korinth via B4 Relay 2024-11-11 7:05 ` [PATCH v3 0/3] rust: Add pr_*_once macros Dirk Behme 3 siblings, 0 replies; 15+ messages in thread From: Jens Korinth via B4 Relay @ 2024-11-09 20:30 UTC (permalink / raw) To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross Cc: rust-for-linux, FUJITA Tomonori, Dirk Behme, Jens Korinth From: FUJITA Tomonori <fujita.tomonori@gmail.com> Add Rust version of pr_[emerg|alert|crit|err|warn|notic|info]_once functions, which print a message only once. Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com> Signed-off-by: Jens Korinth <jens.korinth@tuta.io> --- rust/kernel/print.rs | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs index 9c7434b221984ad325138e5dc90ab4340cd0be2e..26542100be1ca843a0f916bd41260e20ec1f1b0e 100644 --- a/rust/kernel/print.rs +++ b/rust/kernel/print.rs @@ -448,3 +448,129 @@ macro_rules! do_once_lite ( } ); ); + +/// Prints an emergency-level message (level 0) only once. +/// +/// Equivalent to the kernel's [`pr_emerg_once`] macro. +/// +/// [`pr_emerg_once`]: srctree/include/linux/printk.h +/// +/// # Examples +/// +/// ``` +/// kernel::pr_emerg_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_emerg_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_emerg!($($arg)*)) + ) +); + +/// Prints an alert-level message (level 1) only once. +/// +/// Equivalent to the kernel's [`pr_alert_once`] macro. +/// +/// [`pr_alert_once`]: srctree/include/linux/printk.h +/// +/// # Examples +/// +/// ``` +/// kernel::pr_alert_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_alert_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_alert!($($arg)*)) + ) +); + +/// Prints a critical-level message (level 2) only once. +/// +/// Equivalent to the kernel's [`pr_crit_once`] macro. +/// +/// [`pr_crit_once`]: srctree/include/linux/printk.h +/// +/// # Examples +/// +/// ``` +/// kernel::pr_crit_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_crit_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_crit!($($arg)*)) + ) +); + +/// Prints an error-level message (level 3) only once. +/// +/// Equivalent to the kernel's [`pr_err_once`] macro. +/// +/// # Examples +/// +/// [`pr_err_once`]: srctree/include/linux/printk.h +/// +/// ``` +/// kernel::pr_err_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_err_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_err!($($arg)*)) + ) +); + +/// Prints a warning-level message (level 4) only once. +/// +/// Equivalent to the kernel's [`pr_warn_once`] macro. +/// +/// [`pr_warn_once`]: srctree/include/linux/printk.h +/// +/// # Examples +/// +/// ``` +/// kernel::pr_warn_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_warn_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_warn!($($arg)*)) + ) +); + +/// Prints a notice-level message (level 5) only once. +/// +/// Equivalent to the kernel's [`pr_notice_once`] macro. +/// +/// [`pr_notice_once`]: srctree/include/linux/printk.h +/// +/// # Examples +/// +/// ``` +/// kernel::pr_notice_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_notice_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_notice!($($arg)*)) + ) +); + +/// Prints an info-level message (level 6) only once. +/// +/// Equivalent to the kernel's [`pr_info_once`] macro. +/// +/// [`pr_info_once`]: srctree/include/linux/printk.h +/// +/// # Examples +/// +/// ``` +/// kernel::pr_info_once!("hello {}\n", "there"); +/// ``` +#[macro_export] +macro_rules! pr_info_once ( + ($($arg:tt)*) => ( + $crate::do_once_lite!($crate::pr_info!($($arg)*)) + ) +); -- 2.44.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 3/3] rust: error: Replace pr_warn by pr_warn_once 2024-11-09 20:30 [PATCH v3 0/3] rust: Add pr_*_once macros Jens Korinth via B4 Relay 2024-11-09 20:30 ` [PATCH v3 1/3] rust: print: Add do_once_lite macro Jens Korinth via B4 Relay 2024-11-09 20:30 ` [PATCH v3 2/3] rust: print: Add pr_*_once macros Jens Korinth via B4 Relay @ 2024-11-09 20:30 ` Jens Korinth via B4 Relay 2024-11-11 7:05 ` [PATCH v3 0/3] rust: Add pr_*_once macros Dirk Behme 3 siblings, 0 replies; 15+ messages in thread From: Jens Korinth via B4 Relay @ 2024-11-09 20:30 UTC (permalink / raw) To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross Cc: rust-for-linux, FUJITA Tomonori, Dirk Behme, Jens Korinth From: Jens Korinth <jens.korinth@tuta.io> Use new pr_warn_once macro to resolve TODO in error.rs. Signed-off-by: Jens Korinth <jens.korinth@tuta.io> --- rust/kernel/error.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 7cd3bbab52f208961390de03a255446950e9eb04..fe1b31506b30fba0ec9d5339d80c2a7fa76ce7c7 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -102,8 +102,7 @@ impl Error { /// be returned in such a case. pub fn from_errno(errno: core::ffi::c_int) -> Error { if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 { - // TODO: Make it a `WARN_ONCE` once available. - crate::pr_warn!( + crate::pr_warn_once!( "attempted to create `Error` with out of range `errno`: {}", errno ); -- 2.44.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 0/3] rust: Add pr_*_once macros 2024-11-09 20:30 [PATCH v3 0/3] rust: Add pr_*_once macros Jens Korinth via B4 Relay ` (2 preceding siblings ...) 2024-11-09 20:30 ` [PATCH v3 3/3] rust: error: Replace pr_warn by pr_warn_once Jens Korinth via B4 Relay @ 2024-11-11 7:05 ` Dirk Behme 3 siblings, 0 replies; 15+ messages in thread From: Dirk Behme @ 2024-11-11 7:05 UTC (permalink / raw) To: jens.korinth, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross Cc: rust-for-linux, FUJITA Tomonori, Dirk Behme On 09.11.2024 21:30, Jens Korinth via B4 Relay wrote: > Add Rust version of pr_[emerg|alert|crit|err|warn|notic|info]_once > functions, which print a message only once. > > v3: > - Fix rustdoc error, formatting issues > - Fix missing Signed-off-by Many thanks for updating! It compiles on top of rust-next for me. Running it I get the 'Examples' output. So in case it helps: Tested-by: Dirk Behme <dirk.behme@de.bosch.com> Thanks! Dirk ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2024-11-11 17:46 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-11-09 20:30 [PATCH v3 0/3] rust: Add pr_*_once macros Jens Korinth via B4 Relay 2024-11-09 20:30 ` [PATCH v3 1/3] rust: print: Add do_once_lite macro Jens Korinth via B4 Relay 2024-11-09 20:41 ` Miguel Ojeda 2024-11-09 21:33 ` jens.korinth 2024-11-09 21:44 ` Miguel Ojeda 2024-11-09 22:56 ` Boqun Feng 2024-11-10 7:45 ` jens.korinth 2024-11-10 19:23 ` Boqun Feng 2024-11-11 9:17 ` Alice Ryhl 2024-11-11 13:34 ` jens.korinth 2024-11-11 13:53 ` Alice Ryhl 2024-11-11 17:46 ` Boqun Feng 2024-11-09 20:30 ` [PATCH v3 2/3] rust: print: Add pr_*_once macros Jens Korinth via B4 Relay 2024-11-09 20:30 ` [PATCH v3 3/3] rust: error: Replace pr_warn by pr_warn_once Jens Korinth via B4 Relay 2024-11-11 7:05 ` [PATCH v3 0/3] rust: Add pr_*_once macros Dirk Behme
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).