Skip to content

Commit

Permalink
rust: sync: Makes CondVar::wait() an uninterruptible wait
Browse files Browse the repository at this point in the history
Currently, `CondVar::wait()` is an interruptible wait, and this is
different than `wait_event()` in include/linux/wait.h (which is an
uninterruptible wait). To avoid confusion between different APIs on the
interruptible/uninterruptible, make `CondVar::wait()` an uninterruptible
wait same as `wait_event()`, also rename the old `wait()` to
`CondVar::wait_interruptible()`.

Spotted-by: Tiago Lam <[email protected]>
Signed-off-by: Boqun Feng <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Alice Ryhl <[email protected]>
Reviewed-by: Tiago Lam <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Miguel Ojeda <[email protected]>
  • Loading branch information
fbq authored and ojeda committed Dec 21, 2023
1 parent 80fe9e5 commit 0a7f5ba
Showing 1 changed file with 14 additions and 14 deletions.
28 changes: 14 additions & 14 deletions rust/kernel/sync/condvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ macro_rules! new_condvar {
/// fn wait_for_value(e: &Example, v: u32) {
/// let mut guard = e.value.lock();
/// while *guard != v {
/// e.value_changed.wait_uninterruptible(&mut guard);
/// e.value_changed.wait(&mut guard);
/// }
/// }
///
Expand Down Expand Up @@ -120,28 +120,28 @@ impl CondVar {
unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) };
}

/// Releases the lock and waits for a notification in interruptible mode.
/// Releases the lock and waits for a notification in uninterruptible mode.
///
/// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
/// thread to sleep, reacquiring the lock on wake up. It wakes up when notified by
/// [`CondVar::notify_one`] or [`CondVar::notify_all`], or when the thread receives a signal.
/// It may also wake up spuriously.
/// [`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);
}

/// Releases the lock and waits for a notification in interruptible mode.
///
/// Similar to [`CondVar::wait`], except that the wait is interruptible. That is, the thread may
/// wake up due to signals. It may also wake up spuriously.
///
/// Returns whether there is a signal pending.
#[must_use = "wait returns if a signal is pending, so the caller must check the return value"]
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
#[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);
crate::current!().signal_pending()
}

/// Releases the lock and waits for a notification in uninterruptible mode.
///
/// Similar to [`CondVar::wait`], except that the wait is not interruptible. That is, the
/// thread won't wake up due to signals. It may, however, wake up supirously.
pub fn wait_uninterruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard)
}

/// 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.
Expand Down

0 comments on commit 0a7f5ba

Please sign in to comment.