[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <433dcb57-e5d6-bb2b-5c5a-74768cccecab@ryhl.io>
Date: Fri, 14 Apr 2023 13:55:20 +0200
From: Alice Ryhl <alice@...l.io>
To: Wedson Almeida Filho <wedsonaf@...il.com>,
rust-for-linux@...r.kernel.org
Cc: Miguel Ojeda <ojeda@...nel.org>,
Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
linux-kernel@...r.kernel.org,
Wedson Almeida Filho <walmeida@...rosoft.com>,
Peter Zijlstra <peterz@...radead.org>,
Ingo Molnar <mingo@...hat.com>, Will Deacon <will@...nel.org>,
Waiman Long <longman@...hat.com>,
Martin Rodriguez Reboredo <yakoyoku@...il.com>
Subject: Re: [PATCH v4 12/13] rust: sync: introduce `CondVar`
On 4/11/23 07:45, Wedson Almeida Filho wrote:
> From: Wedson Almeida Filho <walmeida@...rosoft.com>
>
> This is the traditional condition variable or monitor synchronisation
> primitive. It is implemented with C's `wait_queue_head_t`.
>
> It allows users to release a lock and go to sleep while guaranteeing
> that notifications won't be missed. This is achieved by enqueuing a wait
> entry before releasing the lock.
>
> Cc: Peter Zijlstra <peterz@...radead.org>
> Cc: Ingo Molnar <mingo@...hat.com>
> Cc: Will Deacon <will@...nel.org>
> Cc: Waiman Long <longman@...hat.com>
> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@...il.com>
> Signed-off-by: Wedson Almeida Filho <walmeida@...rosoft.com>
Reviewed-by: Alice Ryhl <aliceryhl@...gle.com>
I have a few methods below that the binder driver will need on the
condvar. I'll let it be up to you whether you wish to include them in
this patch. Otherwise, we will add them when we start upstreaming binder.
> + /// 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, 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.
> + ///
> + /// 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 {
> + self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard);
> + crate::current!().signal_pending()
> + }
The binder driver will need a `wait_timeout` method.
> + /// 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.
> + unsafe {
> + bindings::__wake_up(
> + self.wait_list.get(),
> + bindings::TASK_NORMAL,
> + count,
> + flags as _,
> + )
> + };
> + }
> +
> + /// Wakes a single waiter up, if any.
> + ///
> + /// 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);
> + }
> +
> + /// Wakes all waiters up, if any.
> + ///
> + /// 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);
> + }
Android binder will also need a `notify_sync` method. It could be
implemented like this:
/// Calls the kernel function to notify one thread synchronously.
pub fn notify_sync(&self) {
// SAFETY: `wait_list` points to valid memory.
unsafe { bindings::__wake_up_sync(self.wait_list.get(),
bindings::TASK_NORMAL) };
}
Powered by blists - more mailing lists