* [PATCH v1 0/2] add Rust version of might_sleep()
@ 2025-04-06 11:07 FUJITA Tomonori
2025-04-06 11:07 ` [PATCH v1 1/2] sched/core: Add __might_sleep_precision() FUJITA Tomonori
2025-04-06 11:07 ` [PATCH v1 2/2] rust: task: add Rust version of might_sleep() FUJITA Tomonori
0 siblings, 2 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2025-04-06 11:07 UTC (permalink / raw)
To: linux-kernel, rust-for-linux
Cc: boqun.feng, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
a.hindborg, aliceryhl, tmgross, dakr, mingo, peterz, juri.lelli,
vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman,
vschneid, pmladek
This patchset adds Rust version of might_sleep().
These patches were previously part of the IO polling patchset [1], but
they were split out to make upstreaming easier.
The first patch is for sched/core, which adds
__might_sleep_precision(), rust friendly version of __might_sleep(),
which takes a pointer to a string with the length instead of a
null-terminated string. Rust's core::panic::Location::file(), which
gives the file name of a caller, doesn't provide a null-terminated
string. __might_sleep_precision() uses a precision specifier in the
printk format, which specifies the length of a string; a string
doesn't need to be a null-terminated. Providing a null-terminated
string for better C interoperability is under discussion [2].
The second patch adds a Rust implementation of might_sleep(), on top
of the changes in the first patch.
[1]: https://lore.kernel.org/lkml/20250220070611.214262-1-fujita.tomonori@gmail.com/
[2]: https://github.com/rust-lang/libs-team/issues/466
FUJITA Tomonori (2):
sched/core: Add __might_sleep_precision()
rust: task: add Rust version of might_sleep()
include/linux/kernel.h | 2 ++
kernel/sched/core.c | 62 ++++++++++++++++++++++++++++--------------
rust/helpers/task.c | 6 ++++
rust/kernel/task.rs | 26 ++++++++++++++++++
4 files changed, 75 insertions(+), 21 deletions(-)
base-commit: f4d2ef48250ad057e4f00087967b5ff366da9f39
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v1 1/2] sched/core: Add __might_sleep_precision()
2025-04-06 11:07 [PATCH v1 0/2] add Rust version of might_sleep() FUJITA Tomonori
@ 2025-04-06 11:07 ` FUJITA Tomonori
2025-04-06 11:07 ` [PATCH v1 2/2] rust: task: add Rust version of might_sleep() FUJITA Tomonori
1 sibling, 0 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2025-04-06 11:07 UTC (permalink / raw)
To: linux-kernel, rust-for-linux
Cc: Daniel Almeida, Alice Ryhl, Boqun Feng, ojeda, alex.gaynor, gary,
bjorn3_gh, benno.lossin, a.hindborg, tmgross, dakr, mingo, peterz,
juri.lelli, vincent.guittot, dietmar.eggemann, rostedt, bsegall,
mgorman, vschneid, pmladek
Add __might_sleep_precision(), Rust friendly version of
__might_sleep(), which takes a pointer to a string with the length
instead of a null-terminated string.
Rust's core::panic::Location::file(), which gives the file name of a
caller, doesn't provide a null-terminated
string. __might_sleep_precision() uses a precision specifier in the
printk format, which specifies the length of a string; a string
doesn't need to be a null-terminated.
Modify __might_sleep() to call __might_sleep_precision() but the
impact should be negligible. When printing the error (sleeping
function called from invalid context), the precision string format is
used instead of the simple string format; the precision specifies the
the maximum length of the displayed string.
Note that Location::file() providing a null-terminated string for
better C interoperability is under discussion [1].
[1]: https://github.com/rust-lang/libs-team/issues/466
Tested-by: Daniel Almeida <daniel.almeida@collabora.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
include/linux/kernel.h | 2 ++
kernel/sched/core.c | 62 ++++++++++++++++++++++++++++--------------
2 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index be2e8c0a187e..086ee1dc447e 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -87,6 +87,7 @@ extern int dynamic_might_resched(void);
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
extern void __might_resched(const char *file, int line, unsigned int offsets);
extern void __might_sleep(const char *file, int line);
+extern void __might_sleep_precision(const char *file, int len, int line);
extern void __cant_sleep(const char *file, int line, int preempt_offset);
extern void __cant_migrate(const char *file, int line);
@@ -145,6 +146,7 @@ extern void __cant_migrate(const char *file, int line);
static inline void __might_resched(const char *file, int line,
unsigned int offsets) { }
static inline void __might_sleep(const char *file, int line) { }
+static inline void __might_sleep_precision(const char *file, int len, int line) { }
# define might_sleep() do { might_resched(); } while (0)
# define cant_sleep() do { } while (0)
# define cant_migrate() do { } while (0)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index cfaca3040b2f..f212e1706d5a 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8730,24 +8730,6 @@ void __init sched_init(void)
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
-void __might_sleep(const char *file, int line)
-{
- unsigned int state = get_current_state();
- /*
- * Blocking primitives will set (and therefore destroy) current->state,
- * since we will exit with TASK_RUNNING make sure we enter with it,
- * otherwise we will destroy state.
- */
- WARN_ONCE(state != TASK_RUNNING && current->task_state_change,
- "do not call blocking ops when !TASK_RUNNING; "
- "state=%x set at [<%p>] %pS\n", state,
- (void *)current->task_state_change,
- (void *)current->task_state_change);
-
- __might_resched(file, line, 0);
-}
-EXPORT_SYMBOL(__might_sleep);
-
static void print_preempt_disable_ip(int preempt_offset, unsigned long ip)
{
if (!IS_ENABLED(CONFIG_DEBUG_PREEMPT))
@@ -8769,7 +8751,8 @@ static inline bool resched_offsets_ok(unsigned int offsets)
return nested == offsets;
}
-void __might_resched(const char *file, int line, unsigned int offsets)
+static void __might_resched_precision(const char *file, int file_len, int line,
+ unsigned int offsets)
{
/* Ratelimiting timestamp: */
static unsigned long prev_jiffy;
@@ -8792,8 +8775,8 @@ void __might_resched(const char *file, int line, unsigned int offsets)
/* Save this before calling printk(), since that will clobber it: */
preempt_disable_ip = get_preempt_disable_ip(current);
- pr_err("BUG: sleeping function called from invalid context at %s:%d\n",
- file, line);
+ pr_err("BUG: sleeping function called from invalid context at %.*s:%d\n",
+ file_len, file, line);
pr_err("in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n",
in_atomic(), irqs_disabled(), current->non_block_count,
current->pid, current->comm);
@@ -8818,8 +8801,45 @@ void __might_resched(const char *file, int line, unsigned int offsets)
dump_stack();
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
}
+
+/*
+ * The precision in vsnprintf() specifies the maximum length of the
+ * displayed string. The precision needs to be larger than the actual
+ * length of the string, so a sufficiently large value should be used
+ * for the filename length.
+ */
+#define MAX_FILENAME_LEN (1<<14)
+
+void __might_resched(const char *file, int line, unsigned int offsets)
+{
+ __might_resched_precision(file, MAX_FILENAME_LEN, line, offsets);
+}
EXPORT_SYMBOL(__might_resched);
+void __might_sleep_precision(const char *file, int len, int line)
+{
+ unsigned int state = get_current_state();
+ /*
+ * Blocking primitives will set (and therefore destroy) current->state,
+ * since we will exit with TASK_RUNNING make sure we enter with it,
+ * otherwise we will destroy state.
+ */
+ WARN_ONCE(state != TASK_RUNNING && current->task_state_change,
+ "do not call blocking ops when !TASK_RUNNING; "
+ "state=%x set at [<%p>] %pS\n", state,
+ (void *)current->task_state_change,
+ (void *)current->task_state_change);
+
+ __might_resched_precision(file, len, line, 0);
+}
+EXPORT_SYMBOL_GPL(__might_sleep_precision);
+
+void __might_sleep(const char *file, int line)
+{
+ __might_sleep_precision(file, MAX_FILENAME_LEN, line);
+}
+EXPORT_SYMBOL(__might_sleep);
+
void __cant_sleep(const char *file, int line, int preempt_offset)
{
static unsigned long prev_jiffy;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v1 2/2] rust: task: add Rust version of might_sleep()
2025-04-06 11:07 [PATCH v1 0/2] add Rust version of might_sleep() FUJITA Tomonori
2025-04-06 11:07 ` [PATCH v1 1/2] sched/core: Add __might_sleep_precision() FUJITA Tomonori
@ 2025-04-06 11:07 ` FUJITA Tomonori
2025-04-09 8:51 ` Alice Ryhl
1 sibling, 1 reply; 5+ messages in thread
From: FUJITA Tomonori @ 2025-04-06 11:07 UTC (permalink / raw)
To: linux-kernel, rust-for-linux
Cc: boqun.feng, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
a.hindborg, aliceryhl, tmgross, dakr, mingo, peterz, juri.lelli,
vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman,
vschneid, pmladek
Adds a helper function equivalent to the C's might_sleep(), which
serves as a debugging aid and a potential scheduling point.
Note that this function can only be used in a nonatomic context.
This will be used by Rust version of read_poll_timeout().
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/helpers/task.c | 6 ++++++
rust/kernel/task.rs | 26 ++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/rust/helpers/task.c b/rust/helpers/task.c
index 31c33ea2dce6..2c85bbc2727e 100644
--- a/rust/helpers/task.c
+++ b/rust/helpers/task.c
@@ -1,7 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
#include <linux/sched/task.h>
+void rust_helper_might_resched(void)
+{
+ might_resched();
+}
+
struct task_struct *rust_helper_get_current(void)
{
return current;
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 9e6f6854948d..1f0156b38ab5 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -380,3 +380,29 @@ fn eq(&self, other: &Kuid) -> bool {
}
impl Eq for Kuid {}
+
+/// Annotation for functions that can sleep.
+///
+/// Equivalent to the C side [`might_sleep()`], this function serves as
+/// a debugging aid and a potential scheduling point.
+///
+/// This function can only be used in a nonatomic context.
+#[track_caller]
+#[inline]
+pub fn might_sleep() {
+ #[cfg(CONFIG_DEBUG_ATOMIC_SLEEP)]
+ {
+ let loc = core::panic::Location::caller();
+ // SAFETY: FFI call.
+ unsafe {
+ crate::bindings::__might_sleep_precision(
+ loc.file().as_ptr().cast(),
+ loc.file().len() as i32,
+ loc.line() as i32,
+ )
+ }
+ }
+
+ // SAFETY: FFI call.
+ unsafe { crate::bindings::might_resched() }
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v1 2/2] rust: task: add Rust version of might_sleep()
2025-04-06 11:07 ` [PATCH v1 2/2] rust: task: add Rust version of might_sleep() FUJITA Tomonori
@ 2025-04-09 8:51 ` Alice Ryhl
2025-04-10 13:47 ` FUJITA Tomonori
0 siblings, 1 reply; 5+ messages in thread
From: Alice Ryhl @ 2025-04-09 8:51 UTC (permalink / raw)
To: FUJITA Tomonori
Cc: linux-kernel, rust-for-linux, boqun.feng, ojeda, alex.gaynor,
gary, bjorn3_gh, benno.lossin, a.hindborg, tmgross, dakr, mingo,
peterz, juri.lelli, vincent.guittot, dietmar.eggemann, rostedt,
bsegall, mgorman, vschneid, pmladek
On Sun, Apr 06, 2025 at 08:07:18PM +0900, FUJITA Tomonori wrote:
> Adds a helper function equivalent to the C's might_sleep(), which
> serves as a debugging aid and a potential scheduling point.
>
> Note that this function can only be used in a nonatomic context.
>
> This will be used by Rust version of read_poll_timeout().
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
> rust/helpers/task.c | 6 ++++++
> rust/kernel/task.rs | 26 ++++++++++++++++++++++++++
> 2 files changed, 32 insertions(+)
>
> diff --git a/rust/helpers/task.c b/rust/helpers/task.c
> index 31c33ea2dce6..2c85bbc2727e 100644
> --- a/rust/helpers/task.c
> +++ b/rust/helpers/task.c
> @@ -1,7 +1,13 @@
> // SPDX-License-Identifier: GPL-2.0
>
> +#include <linux/kernel.h>
> #include <linux/sched/task.h>
>
> +void rust_helper_might_resched(void)
> +{
> + might_resched();
> +}
> +
> struct task_struct *rust_helper_get_current(void)
> {
> return current;
> diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
> index 9e6f6854948d..1f0156b38ab5 100644
> --- a/rust/kernel/task.rs
> +++ b/rust/kernel/task.rs
> @@ -380,3 +380,29 @@ fn eq(&self, other: &Kuid) -> bool {
> }
>
> impl Eq for Kuid {}
> +
> +/// Annotation for functions that can sleep.
> +///
> +/// Equivalent to the C side [`might_sleep()`], this function serves as
> +/// a debugging aid and a potential scheduling point.
> +///
> +/// This function can only be used in a nonatomic context.
> +#[track_caller]
> +#[inline]
> +pub fn might_sleep() {
> + #[cfg(CONFIG_DEBUG_ATOMIC_SLEEP)]
> + {
> + let loc = core::panic::Location::caller();
> + // SAFETY: FFI call.
Overall this looks okay to me, but this safety comment could be
improved. This being an FFI call is not the reason *why* it is safe to
make this call.
// SAFETY: `file.as_ptr()` is valid for reading for `file.len()` bytes.
And I might separate the file into a separate variable for clarity:
let loc = core::panic::Location::caller();
let file = loc.file();
> + unsafe {
> + crate::bindings::__might_sleep_precision(
> + loc.file().as_ptr().cast(),
> + loc.file().len() as i32,
> + loc.line() as i32,
> + )
> + }
> + }
> +
> + // SAFETY: FFI call.
> + unsafe { crate::bindings::might_resched() }
And here you can say
// SAFETY: Always safe to call.
Alice
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1 2/2] rust: task: add Rust version of might_sleep()
2025-04-09 8:51 ` Alice Ryhl
@ 2025-04-10 13:47 ` FUJITA Tomonori
0 siblings, 0 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2025-04-10 13:47 UTC (permalink / raw)
To: aliceryhl
Cc: fujita.tomonori, linux-kernel, rust-for-linux, boqun.feng, ojeda,
alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg, tmgross,
dakr, mingo, peterz, juri.lelli, vincent.guittot,
dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, pmladek
On Wed, 9 Apr 2025 08:51:44 +0000
Alice Ryhl <aliceryhl@google.com> wrote:
>> diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
>> index 9e6f6854948d..1f0156b38ab5 100644
>> --- a/rust/kernel/task.rs
>> +++ b/rust/kernel/task.rs
>> @@ -380,3 +380,29 @@ fn eq(&self, other: &Kuid) -> bool {
>> }
>>
>> impl Eq for Kuid {}
>> +
>> +/// Annotation for functions that can sleep.
>> +///
>> +/// Equivalent to the C side [`might_sleep()`], this function serves as
>> +/// a debugging aid and a potential scheduling point.
>> +///
>> +/// This function can only be used in a nonatomic context.
>> +#[track_caller]
>> +#[inline]
>> +pub fn might_sleep() {
>> + #[cfg(CONFIG_DEBUG_ATOMIC_SLEEP)]
>> + {
>> + let loc = core::panic::Location::caller();
>> + // SAFETY: FFI call.
>
> Overall this looks okay to me, but this safety comment could be
> improved. This being an FFI call is not the reason *why* it is safe to
> make this call.
Undertood.
> // SAFETY: `file.as_ptr()` is valid for reading for `file.len()` bytes.
>
> And I might separate the file into a separate variable for clarity:
> let loc = core::panic::Location::caller();
> let file = loc.file();
Fixed.
>> + unsafe {
>> + crate::bindings::__might_sleep_precision(
>> + loc.file().as_ptr().cast(),
>> + loc.file().len() as i32,
>> + loc.line() as i32,
>> + )
>> + }
>> + }
>> +
>> + // SAFETY: FFI call.
>> + unsafe { crate::bindings::might_resched() }
>
> And here you can say
> // SAFETY: Always safe to call.
Fixed.
Thanks a lot!
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-04-10 13:47 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-06 11:07 [PATCH v1 0/2] add Rust version of might_sleep() FUJITA Tomonori
2025-04-06 11:07 ` [PATCH v1 1/2] sched/core: Add __might_sleep_precision() FUJITA Tomonori
2025-04-06 11:07 ` [PATCH v1 2/2] rust: task: add Rust version of might_sleep() FUJITA Tomonori
2025-04-09 8:51 ` Alice Ryhl
2025-04-10 13:47 ` FUJITA Tomonori
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).