2024-01-08 14:50:18

by Alice Ryhl

[permalink] [raw]
Subject: [PATCH v4 0/4] Additional CondVar methods needed by Rust Binder

This patchset contains some CondVar methods that Rust Binder needs.

The CondVar type implements a condition variable, and tries to mirror
the API of the CondVar type provided by the Rust standard library [2].
It is implemented using a `wait_queue_head`.

Please see the Rust Binder RFC for usage examples [1].

Users of rust: sync: add `CondVar::notify_sync`:
[PATCH RFC 04/20] rust_binder: add work lists
[PATCH RFC 07/20] rust_binder: add epoll support
[PATCH RFC 08/20] rust_binder: add non-oneway transactions

Users of rust: time: add msecs to jiffies conversion:
[PATCH v2 3/3] rust: sync: add `CondVar::wait_timeout`
[PATCH RFC 15/20] rust_binder: add process freezing

Users of rust: sync: add `CondVar::wait_timeout`:
[PATCH RFC 15/20] rust_binder: add process freezing

This patchset is based on top of the rust-6.8 tag.

Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [1]
Link: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html [2]
Link: https://lore.kernel.org/all/[email protected]/ [3]
Signed-off-by: Alice Ryhl <[email protected]>
---
Changes in v4:
- Fix imports.
- Improve documentation for `notify_sync`.
- Add justification for using a jiffies-based `wait_timeout`.
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- Update module description for new `time` module.
- Move constants to `rust/kernel/task.rs`.
- Fix incorrect doc-comment on `CondVar::notify`.
- Rename c_long argument to `timeout_in_jiffies`.
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Introduce "rust: time: add msecs to jiffies conversion" patch.
- Introduce "rust: sync: update integer types in CondVar" patch.
- Merge wait_internal and wait_internal_timeout.
- Use new Jiffies type alias instead of u64.
- Update names to use _interruptable suffix (and base patchset on top of [3]).
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Alice Ryhl (4):
rust: sync: add `CondVar::notify_sync`
rust: time: add msecs to jiffies conversion
rust: sync: add `CondVar::wait_timeout`
rust: sync: update integer types in CondVar

rust/bindings/bindings_helper.h | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/sync/condvar.rs | 95 ++++++++++++++++++++++++++++++++---------
rust/kernel/sync/lock.rs | 4 +-
rust/kernel/task.rs | 18 +++++++-
rust/kernel/time.rs | 20 +++++++++
6 files changed, 117 insertions(+), 22 deletions(-)
---
base-commit: 711cbfc717650532624ca9f56fbaf191bed56e67
change-id: 20231205-rb-new-condvar-methods-27ba95df5d41

Best regards,
--
Alice Ryhl <[email protected]>



2024-01-08 14:50:32

by Alice Ryhl

[permalink] [raw]
Subject: [PATCH v4 1/4] rust: sync: add `CondVar::notify_sync`

Wake up another thread synchronously.

This method behaves like `notify_one`, except that it hints to the
scheduler that the current thread is about to go to sleep, so it should
schedule the target thread on the same CPU.

This is used by Rust Binder as a performance optimization. When sending
a transaction to a different process, we usually know which thread will
handle it, so we can schedule that thread for execution next on this
CPU for better cache locality.

Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Martin Rodriguez Reboredo <[email protected]>
Reviewed-by: Tiago Lam <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
---
rust/kernel/sync/condvar.rs | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index f65e19d5a37c..b323a0c26513 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -155,6 +155,16 @@ fn notify(&self, count: i32, flags: u32) {
};
}

+ /// Calls the kernel function to notify one thread synchronously.
+ ///
+ /// This method behaves like `notify_one`, except that it hints to the scheduler that the
+ /// current thread is about to go to sleep, so it should schedule the target thread on the same
+ /// CPU.
+ pub fn notify_sync(&self) {
+ // SAFETY: `wait_list` points to valid memory.
+ unsafe { bindings::__wake_up_sync(self.wait_list.get(), bindings::TASK_NORMAL) };
+ }
+
/// Wakes a single waiter up, if any.
///
/// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost

--
2.43.0.472.g3155946c3a-goog


2024-01-08 14:50:47

by Alice Ryhl

[permalink] [raw]
Subject: [PATCH v4 2/4] rust: time: add msecs to jiffies conversion

Defines type aliases and conversions for msecs and jiffies.

This is used by Rust Binder for process freezing. There, we want to
sleep until the freeze operation completes, but we want to be able to
abort the process freezing if it doesn't complete within some timeout.
The freeze timeout is supplied in msecs.

Note that we need to convert to jiffies in Binder. It is not enough to
introduce a variant of `CondVar::wait_timeout` that takes the timeout in
msecs because we need to be able to restart the sleep with the remaining
sleep duration if it is interrupted, and if the API takes msecs rather
than jiffies, then that would require a conversion roundtrip jiffies->
msecs->jiffies that is best avoided.

Suggested-by: Boqun Feng <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Martin Rodriguez Reboredo <[email protected]>
Reviewed-by: Tiago Lam <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
---
rust/bindings/bindings_helper.h | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/time.rs | 20 ++++++++++++++++++++
3 files changed, 22 insertions(+)

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index b5714fb69fe3..227dc9240f3f 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -8,6 +8,7 @@

#include <kunit/test.h>
#include <linux/errname.h>
+#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/refcount.h>
#include <linux/wait.h>
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index e6aff80b521f..d4f90acdd517 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -46,6 +46,7 @@
pub mod str;
pub mod sync;
pub mod task;
+pub mod time;
pub mod types;
pub mod workqueue;

diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
new file mode 100644
index 000000000000..25a896eed468
--- /dev/null
+++ b/rust/kernel/time.rs
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Time related primitives.
+//!
+//! This module contains the kernel APIs related to time and timers that
+//! have been ported or wrapped for usage by Rust code in the kernel.
+
+/// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
+pub type Jiffies = core::ffi::c_ulong;
+
+/// The millisecond time unit.
+pub type Msecs = core::ffi::c_uint;
+
+/// Converts milliseconds to jiffies.
+#[inline]
+pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
+ // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
+ // matter what the argument is.
+ unsafe { bindings::__msecs_to_jiffies(msecs) }
+}

--
2.43.0.472.g3155946c3a-goog


2024-01-08 14:51:03

by Alice Ryhl

[permalink] [raw]
Subject: [PATCH v4 3/4] rust: sync: add `CondVar::wait_timeout`

Sleep on a condition variable with a timeout.

This is used by Rust Binder for process freezing. There, we want to
sleep until the freeze operation completes, but we want to be able to
abort the process freezing if it doesn't complete within some timeout.

Note that it is not enough to avoid jiffies by introducing a variant of
`CondVar::wait_timeout` that takes the timeout in msecs because we need
to be able to restart the sleep with the remaining sleep duration if it
is interrupted, and if the API takes msecs rather than jiffies, then
that would require a conversion roundtrip jiffies->msecs->jiffies that
is best avoided.

Reviewed-by: Martin Rodriguez Reboredo <[email protected]>
Reviewed-by: Tiago Lam <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
---
rust/kernel/sync/condvar.rs | 60 ++++++++++++++++++++++++++++++++++++++++-----
rust/kernel/sync/lock.rs | 4 +--
rust/kernel/task.rs | 5 +++-
3 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index b323a0c26513..fa38c095cbe0 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -6,7 +6,11 @@
//! variable.

use super::{lock::Backend, lock::Guard, LockClassKey};
-use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque};
+use crate::{
+ bindings, init::PinInit, pin_init, str::CStr, task::MAX_SCHEDULE_TIMEOUT, time::Jiffies,
+ types::Opaque,
+};
+use core::ffi::c_long;
use core::marker::PhantomPinned;
use macros::pin_data;

@@ -102,7 +106,12 @@ pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self
})
}

- fn wait_internal<T: ?Sized, B: Backend>(&self, wait_state: u32, guard: &mut Guard<'_, T, B>) {
+ fn wait_internal<T: ?Sized, B: Backend>(
+ &self,
+ wait_state: u32,
+ guard: &mut Guard<'_, T, B>,
+ timeout_in_jiffies: c_long,
+ ) -> c_long {
let wait = Opaque::<bindings::wait_queue_entry>::uninit();

// SAFETY: `wait` points to valid memory.
@@ -113,11 +122,13 @@ fn wait_internal<T: ?Sized, B: Backend>(&self, wait_state: u32, guard: &mut Guar
bindings::prepare_to_wait_exclusive(self.wait_list.get(), wait.get(), wait_state as _)
};

- // SAFETY: No arguments, switches to another thread.
- guard.do_unlocked(|| unsafe { bindings::schedule() });
+ // SAFETY: Switches to another thread. The timeout can be any number.
+ let ret = guard.do_unlocked(|| unsafe { bindings::schedule_timeout(timeout_in_jiffies) });

// SAFETY: Both `wait` and `wait_list` point to valid memory.
unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) };
+
+ ret
}

/// Releases the lock and waits for a notification in uninterruptible mode.
@@ -127,7 +138,7 @@ fn wait_internal<T: ?Sized, B: Backend>(&self, wait_state: u32, guard: &mut Guar
/// [`CondVar::notify_one`] or [`CondVar::notify_all`]. Note that it may also wake up
/// spuriously.
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
- self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard);
+ self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
}

/// Releases the lock and waits for a notification in interruptible mode.
@@ -138,10 +149,31 @@ pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
/// Returns whether there is a signal pending.
#[must_use = "wait_interruptible returns if a signal is pending, so the caller must check the return value"]
pub fn wait_interruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
- self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard);
+ self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
crate::current!().signal_pending()
}

+ /// Releases the lock and waits for a notification in interruptible mode.
+ ///
+ /// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
+ /// thread to sleep. It wakes up when notified by [`CondVar::notify_one`] or
+ /// [`CondVar::notify_all`], or when a timeout occurs, or when the thread receives a signal.
+ #[must_use = "wait_interruptible_timeout returns if a signal is pending, so the caller must check the return value"]
+ pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
+ &self,
+ guard: &mut Guard<'_, T, B>,
+ jiffies: Jiffies,
+ ) -> CondVarTimeoutResult {
+ let jiffies = jiffies.try_into().unwrap_or(MAX_SCHEDULE_TIMEOUT);
+ let res = self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard, jiffies);
+
+ match (res as Jiffies, crate::current!().signal_pending()) {
+ (jiffies, true) => CondVarTimeoutResult::Signal { jiffies },
+ (0, false) => CondVarTimeoutResult::Timeout,
+ (jiffies, false) => CondVarTimeoutResult::Woken { jiffies },
+ }
+ }
+
/// Calls the kernel function to notify the appropriate number of threads with the given flags.
fn notify(&self, count: i32, flags: u32) {
// SAFETY: `wait_list` points to valid memory.
@@ -181,3 +213,19 @@ pub fn notify_all(&self) {
self.notify(0, 0);
}
}
+
+/// The return type of `wait_timeout`.
+pub enum CondVarTimeoutResult {
+ /// The timeout was reached.
+ Timeout,
+ /// Somebody woke us up.
+ Woken {
+ /// Remaining sleep duration.
+ jiffies: Jiffies,
+ },
+ /// A signal occurred.
+ Signal {
+ /// Remaining sleep duration.
+ jiffies: Jiffies,
+ },
+}
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index f12a684bc957..149a5259d431 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -139,7 +139,7 @@ pub struct Guard<'a, T: ?Sized, B: Backend> {
unsafe impl<T: Sync + ?Sized, B: Backend> Sync for Guard<'_, T, B> {}

impl<T: ?Sized, B: Backend> Guard<'_, T, B> {
- pub(crate) fn do_unlocked(&mut self, cb: impl FnOnce()) {
+ pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
// SAFETY: The caller owns the lock, so it is safe to unlock it.
unsafe { B::unlock(self.lock.state.get(), &self.state) };

@@ -147,7 +147,7 @@ pub(crate) fn do_unlocked(&mut self, cb: impl FnOnce()) {
let _relock =
ScopeGuard::new(|| unsafe { B::relock(self.lock.state.get(), &mut self.state) });

- cb();
+ cb()
}
}

diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 9451932d5d86..17f14ebb8f48 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -5,7 +5,10 @@
//! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h).

use crate::{bindings, types::Opaque};
-use core::{marker::PhantomData, ops::Deref, ptr};
+use core::{ffi::c_long, marker::PhantomData, ops::Deref, ptr};
+
+/// A sentinal value used for infinite timeouts.
+pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX;

/// Returns the currently running task.
#[macro_export]

--
2.43.0.472.g3155946c3a-goog


2024-01-08 14:51:18

by Alice Ryhl

[permalink] [raw]
Subject: [PATCH v4 4/4] rust: sync: update integer types in CondVar

Reduce the chances of compilation failures due to integer type
mismatches in `CondVar`.

When an integer is defined using a #define in C, bindgen doesn't know
which integer type it is supposed to be, so it will just use `u32` by
default (if it fits in an u32). Whenever the right type is something
else, we insert a cast in Rust. However, this means that the code has a
lot of extra casts, and sometimes the code will be missing casts if u32
happens to be correct on the developer's machine, even though the type
might be something else on a different platform.

This patch updates all uses of such constants in
`rust/kernel/sync/condvar.rs` to use constants defined with the right
type. This allows us to remove various unnecessary casts, while also
future-proofing for the case where `unsigned int != u32`.

I wrote this patch at the suggestion of Benno in [1].

Link: https://lore.kernel.org/all/nAEg-6vbtX72ZY3oirDhrSEf06TBWmMiTt73EklMzEAzN4FD4mF3TPEyAOxBZgZtjzoiaBYtYr3s8sa9wp1uYH9vEWRf2M-Lf4I0BY9rAgk=@proton.me/ [1]
Suggested-by: Benno Lossin <[email protected]>
Reviewed-by: Tiago Lam <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Martin Rodriguez Reboredo <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
---
rust/kernel/sync/condvar.rs | 39 +++++++++++++++++++--------------------
rust/kernel/task.rs | 15 ++++++++++++++-
2 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index fa38c095cbe0..7f2b78e4abc7 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -7,11 +7,17 @@

use super::{lock::Backend, lock::Guard, LockClassKey};
use crate::{
- bindings, init::PinInit, pin_init, str::CStr, task::MAX_SCHEDULE_TIMEOUT, time::Jiffies,
+ bindings,
+ init::PinInit,
+ pin_init,
+ str::CStr,
+ task::{MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE},
+ time::Jiffies,
types::Opaque,
};
-use core::ffi::c_long;
+use core::ffi::{c_int, c_long};
use core::marker::PhantomPinned;
+use core::ptr;
use macros::pin_data;

/// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class.
@@ -108,7 +114,7 @@ pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self

fn wait_internal<T: ?Sized, B: Backend>(
&self,
- wait_state: u32,
+ wait_state: c_int,
guard: &mut Guard<'_, T, B>,
timeout_in_jiffies: c_long,
) -> c_long {
@@ -119,7 +125,7 @@ fn wait_internal<T: ?Sized, B: Backend>(

// SAFETY: Both `wait` and `wait_list` point to valid memory.
unsafe {
- bindings::prepare_to_wait_exclusive(self.wait_list.get(), wait.get(), wait_state as _)
+ bindings::prepare_to_wait_exclusive(self.wait_list.get(), wait.get(), wait_state)
};

// SAFETY: Switches to another thread. The timeout can be any number.
@@ -138,7 +144,7 @@ fn wait_internal<T: ?Sized, B: Backend>(
/// [`CondVar::notify_one`] or [`CondVar::notify_all`]. Note that it may also wake up
/// spuriously.
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
- self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
+ self.wait_internal(TASK_UNINTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
}

/// Releases the lock and waits for a notification in interruptible mode.
@@ -149,7 +155,7 @@ pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
/// Returns whether there is a signal pending.
#[must_use = "wait_interruptible returns if a signal is pending, so the caller must check the return value"]
pub fn wait_interruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
- self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
+ self.wait_internal(TASK_INTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
crate::current!().signal_pending()
}

@@ -165,7 +171,7 @@ pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
jiffies: Jiffies,
) -> CondVarTimeoutResult {
let jiffies = jiffies.try_into().unwrap_or(MAX_SCHEDULE_TIMEOUT);
- let res = self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard, jiffies);
+ let res = self.wait_internal(TASK_INTERRUPTIBLE, guard, jiffies);

match (res as Jiffies, crate::current!().signal_pending()) {
(jiffies, true) => CondVarTimeoutResult::Signal { jiffies },
@@ -174,17 +180,10 @@ pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
}
}

- /// Calls the kernel function to notify the appropriate number of threads with the given flags.
- fn notify(&self, count: i32, flags: u32) {
+ /// Calls the kernel function to notify the appropriate number of threads.
+ fn notify(&self, count: c_int) {
// SAFETY: `wait_list` points to valid memory.
- unsafe {
- bindings::__wake_up(
- self.wait_list.get(),
- bindings::TASK_NORMAL,
- count,
- flags as _,
- )
- };
+ unsafe { bindings::__wake_up(self.wait_list.get(), TASK_NORMAL, count, ptr::null_mut()) };
}

/// Calls the kernel function to notify one thread synchronously.
@@ -194,7 +193,7 @@ fn notify(&self, count: i32, flags: u32) {
/// CPU.
pub fn notify_sync(&self) {
// SAFETY: `wait_list` points to valid memory.
- unsafe { bindings::__wake_up_sync(self.wait_list.get(), bindings::TASK_NORMAL) };
+ unsafe { bindings::__wake_up_sync(self.wait_list.get(), TASK_NORMAL) };
}

/// Wakes a single waiter up, if any.
@@ -202,7 +201,7 @@ pub fn notify_sync(&self) {
/// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost
/// completely (as opposed to automatically waking up the next waiter).
pub fn notify_one(&self) {
- self.notify(1, 0);
+ self.notify(1);
}

/// Wakes all waiters up, if any.
@@ -210,7 +209,7 @@ pub fn notify_one(&self) {
/// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost
/// completely (as opposed to automatically waking up the next waiter).
pub fn notify_all(&self) {
- self.notify(0, 0);
+ self.notify(0);
}
}

diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 17f14ebb8f48..6072b0de4a3e 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -5,11 +5,24 @@
//! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h).

use crate::{bindings, types::Opaque};
-use core::{ffi::c_long, marker::PhantomData, ops::Deref, ptr};
+use core::{
+ ffi::{c_int, c_long, c_uint},
+ marker::PhantomData,
+ ops::Deref,
+ ptr,
+};

/// A sentinal value used for infinite timeouts.
pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX;

+/// Bitmask for tasks that are sleeping in an interruptible state.
+pub const TASK_INTERRUPTIBLE: c_int = bindings::TASK_INTERRUPTIBLE as c_int;
+/// Bitmask for tasks that are sleeping in an uninterruptible state.
+pub const TASK_UNINTERRUPTIBLE: c_int = bindings::TASK_UNINTERRUPTIBLE as c_int;
+/// Convenience constant for waking up tasks regardless of whether they are in interruptible or
+/// uninterruptible sleep.
+pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
+
/// Returns the currently running task.
#[macro_export]
macro_rules! current {

--
2.43.0.472.g3155946c3a-goog


2024-01-10 10:01:49

by Benno Lossin

[permalink] [raw]
Subject: Re: [PATCH v4 3/4] rust: sync: add `CondVar::wait_timeout`

On 08.01.24 15:49, Alice Ryhl wrote:
> Sleep on a condition variable with a timeout.
>
> This is used by Rust Binder for process freezing. There, we want to
> sleep until the freeze operation completes, but we want to be able to
> abort the process freezing if it doesn't complete within some timeout.
>
> Note that it is not enough to avoid jiffies by introducing a variant of
> `CondVar::wait_timeout` that takes the timeout in msecs because we need
> to be able to restart the sleep with the remaining sleep duration if it
> is interrupted, and if the API takes msecs rather than jiffies, then
> that would require a conversion roundtrip jiffies->msecs->jiffies that
> is best avoided.
>
> Reviewed-by: Martin Rodriguez Reboredo <[email protected]>
> Reviewed-by: Tiago Lam <[email protected]>
> Reviewed-by: Boqun Feng <[email protected]>
> Signed-off-by: Alice Ryhl <[email protected]>
> ---
> rust/kernel/sync/condvar.rs | 60 ++++++++++++++++++++++++++++++++++++++++-----
> rust/kernel/sync/lock.rs | 4 +--
> rust/kernel/task.rs | 5 +++-
> 3 files changed, 60 insertions(+), 9 deletions(-)

Reviewed-by: Benno Lossin <[email protected]>

--
Cheers,
Benno


2024-01-24 15:07:52

by Alice Ryhl

[permalink] [raw]
Subject: Re: [PATCH v4 3/4] rust: sync: add `CondVar::wait_timeout`

On Mon, Jan 8, 2024 at 3:50 PM Alice Ryhl <[email protected]> wrote:
> +/// The return type of `wait_timeout`.
> +pub enum CondVarTimeoutResult {
> + /// The timeout was reached.
> + Timeout,
> + /// Somebody woke us up.
> + Woken {
> + /// Remaining sleep duration.
> + jiffies: Jiffies,
> + },
> + /// A signal occurred.
> + Signal {
> + /// Remaining sleep duration.
> + jiffies: Jiffies,
> + },
> +}

I just realized that this needs to be re-exported from kernel::sync.
Otherwise this struct is unreachable, since the kernel::sync::condvar
module is private.

Maybe Miguel can just add that when he picks this?

Alice

2024-01-28 20:04:27

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH v4 0/4] Additional CondVar methods needed by Rust Binder

On Mon, Jan 8, 2024 at 3:50 PM Alice Ryhl <[email protected]> wrote:
>
> This patchset contains some CondVar methods that Rust Binder needs.

Applied to `rust-next` with conflicts resolved after the `wait_list`
rename, added `CondVarTimeoutResult` re-export, fixed typo and added
note on the `sizeof(int)` being unlikely to change.

Alice: please double-check if I missed something.

Thanks everyone!

Cheers,
Miguel

2024-01-29 09:13:30

by Alice Ryhl

[permalink] [raw]
Subject: Re: [PATCH v4 0/4] Additional CondVar methods needed by Rust Binder

On Sun, Jan 28, 2024 at 9:04 PM Miguel Ojeda
<[email protected]> wrote:
>
> On Mon, Jan 8, 2024 at 3:50 PM Alice Ryhl <[email protected]> wrote:
> >
> > This patchset contains some CondVar methods that Rust Binder needs.
>
> Applied to `rust-next` with conflicts resolved after the `wait_list`
> rename, added `CondVarTimeoutResult` re-export, fixed typo and added
> note on the `sizeof(int)` being unlikely to change.
>
> Alice: please double-check if I missed something.

Looks good to me.

Alice