From: "Andreas Hindborg (Samsung)" <nmi@metaspace.dk>
To: Alice Ryhl <aliceryhl@google.com>
Cc: rust-for-linux@vger.kernel.org, "Miguel Ojeda" <ojeda@kernel.org>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Tejun Heo" <tj@kernel.org>,
"Lai Jiangshan" <jiangshanlai@gmail.com>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
linux-kernel@vger.kernel.org, patches@lists.linux.dev
Subject: Re: [PATCH v2 1/8] rust: workqueue: add low-level workqueue bindings
Date: Fri, 02 Jun 2023 16:39:00 +0200 [thread overview]
Message-ID: <87o7ly0vxc.fsf@metaspace.dk> (raw)
In-Reply-To: <20230601134946.3887870-2-aliceryhl@google.com>
Alice Ryhl <aliceryhl@google.com> writes:
> Define basic low-level bindings to a kernel workqueue. The API defined
> here can only be used unsafely. Later commits will provide safe
> wrappers.
>
> Co-developed-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Andreas Hindborg (Samsung) <nmi@metaspace.dk>
> ---
> rust/bindings/bindings_helper.h | 1 +
> rust/kernel/lib.rs | 1 +
> rust/kernel/workqueue.rs | 107 ++++++++++++++++++++++++++++++++
> 3 files changed, 109 insertions(+)
> create mode 100644 rust/kernel/workqueue.rs
>
> diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
> index 50e7a76d5455..ae2e8f018268 100644
> --- a/rust/bindings/bindings_helper.h
> +++ b/rust/bindings/bindings_helper.h
> @@ -10,6 +10,7 @@
> #include <linux/refcount.h>
> #include <linux/wait.h>
> #include <linux/sched.h>
> +#include <linux/workqueue.h>
>
> /* `bindgen` gets confused at certain things. */
> const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 85b261209977..eaded02ffb01 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -43,6 +43,7 @@
> pub mod sync;
> pub mod task;
> pub mod types;
> +pub mod workqueue;
>
> #[doc(hidden)]
> pub use bindings;
> diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
> new file mode 100644
> index 000000000000..9c630840039b
> --- /dev/null
> +++ b/rust/kernel/workqueue.rs
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Work queues.
> +//!
> +//! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h)
> +
> +use crate::{bindings, types::Opaque};
> +
> +/// A kernel work queue.
> +///
> +/// Wraps the kernel's C `struct workqueue_struct`.
> +///
> +/// It allows work items to be queued to run on thread pools managed by the kernel. Several are
> +/// always available, for example, `system`, `system_highpri`, `system_long`, etc.
> +#[repr(transparent)]
> +pub struct Queue(Opaque<bindings::workqueue_struct>);
> +
> +// SAFETY: Kernel workqueues are usable from any thread.
> +unsafe impl Send for Queue {}
> +unsafe impl Sync for Queue {}
> +
> +impl Queue {
> + /// Use the provided `struct workqueue_struct` with Rust.
> + ///
> + /// # Safety
> + ///
> + /// The caller must ensure that the provided raw pointer is not dangling, that it points at a
> + /// valid workqueue, and that it remains valid until the end of 'a.
> + pub unsafe fn from_raw<'a>(ptr: *const bindings::workqueue_struct) -> &'a Queue {
> + // SAFETY: The `Queue` type is `#[repr(transparent)]`, so the pointer cast is valid. The
> + // caller promises that the pointer is not dangling.
> + unsafe { &*(ptr as *const Queue) }
> + }
> +
> + /// Enqueues a work item.
> + ///
> + /// This may fail if the work item is already enqueued in a workqueue.
> + ///
> + /// The work item will be submitted using `WORK_CPU_UNBOUND`.
> + pub fn enqueue<W, const ID: u64>(&self, w: W) -> W::EnqueueOutput
> + where
> + W: RawWorkItem<ID> + Send + 'static,
> + {
> + let queue_ptr = self.0.get();
> +
> + // SAFETY: We only return `false` if the `work_struct` is already in a workqueue. The other
> + // `__enqueue` requirements are not relevant since `W` is `Send` and static.
> + //
> + // The call to `bindings::queue_work_on` will dereference the provided raw pointer, which
> + // is ok because `__enqueue` guarantees that the pointer is valid for the duration of this
> + // closure.
> + //
> + // Furthermore, if the C workqueue code accesses the pointer after this call to
> + // `__enqueue`, then the work item was successfully enqueued, and `bindings::queue_work_on`
> + // will have returned true. In this case, `__enqueue` promises that the raw pointer will
> + // stay valid until we call the function pointer in the `work_struct`, so the access is ok.
> + unsafe {
> + w.__enqueue(move |work_ptr| {
> + bindings::queue_work_on(bindings::WORK_CPU_UNBOUND as _, queue_ptr, work_ptr)
> + })
> + }
> + }
> +}
> +
> +/// A raw work item.
> +///
> +/// This is the low-level trait that is designed for being as general as possible.
> +///
> +/// The `ID` parameter to this trait exists so that a single type can provide multiple
> +/// implementations of this trait. For example, if a struct has multiple `work_struct` fields, then
> +/// you will implement this trait once for each field, using a different id for each field. The
> +/// actual value of the id is not important as long as you use different ids for different fields
> +/// of the same struct. (Fields of different structs need not use different ids.)
> +///
> +/// Note that the id is used only to select the right method to call during compilation. It wont be
> +/// part of the final executable.
> +///
> +/// # Safety
> +///
> +/// Implementers must ensure that any pointers passed to a `queue_work_on` closure by `__enqueue`
> +/// remain valid for the duration specified in the documentation for `__enqueue`.
> +pub unsafe trait RawWorkItem<const ID: u64> {
> + /// The return type of [`Queue::enqueue`].
> + type EnqueueOutput;
> +
> + /// Enqueues this work item on a queue using the provided `queue_work_on` method.
> + ///
> + /// # Guarantees
> + ///
> + /// If this method calls the provided closure, then the raw pointer is guaranteed to point at a
> + /// valid `work_struct` for the duration of the call to the closure. If the closure returns
> + /// true, then it is further guaranteed that the pointer remains valid until someone calls the
> + /// function pointer stored in the `work_struct`.
> + ///
> + /// # Safety
> + ///
> + /// The provided closure may only return `false` if the `work_struct` is already in a workqueue.
> + ///
> + /// If the work item type is annotated with any lifetimes, then you must not call the function
> + /// pointer after any such lifetime expires. (Never calling the function pointer is okay.)
> + ///
> + /// If the work item type is not [`Send`], then the function pointer must be called on the same
> + /// thread as the call to `__enqueue`.
> + unsafe fn __enqueue<F>(self, queue_work_on: F) -> Self::EnqueueOutput
> + where
> + F: FnOnce(*mut bindings::work_struct) -> bool;
> +}
next prev parent reply other threads:[~2023-06-02 14:40 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-01 13:49 [PATCH v2 0/8] rust: workqueue: add bindings for the workqueue Alice Ryhl
2023-06-01 13:49 ` [PATCH v2 1/8] rust: workqueue: add low-level workqueue bindings Alice Ryhl
2023-06-01 14:29 ` Martin Rodriguez Reboredo
2023-06-02 14:39 ` Andreas Hindborg (Samsung) [this message]
2023-06-06 23:36 ` Boqun Feng
2023-06-07 15:18 ` Alice Ryhl
2023-06-11 15:45 ` Benno Lossin
2023-06-01 13:49 ` [PATCH v2 2/8] rust: add offset_of! macro Alice Ryhl
2023-06-01 17:17 ` Gary Guo
2023-06-02 10:33 ` Andreas Hindborg (Samsung)
2023-06-07 15:15 ` Alice Ryhl
2023-06-11 15:47 ` Benno Lossin
2023-06-01 13:49 ` [PATCH v2 3/8] rust: sync: add `Arc::{from_raw, into_raw}` Alice Ryhl
2023-06-01 17:26 ` Gary Guo
2023-06-02 10:51 ` Andreas Hindborg (Samsung)
2023-06-05 14:31 ` Gary Guo
2023-06-05 14:49 ` Andreas Hindborg (Samsung)
2023-06-05 15:00 ` Boqun Feng
2023-06-05 15:20 ` Boqun Feng
2023-06-05 18:34 ` Andreas Hindborg (Samsung)
2023-06-11 15:48 ` Benno Lossin
2023-06-01 13:49 ` [PATCH v2 4/8] rust: workqueue: define built-in queues Alice Ryhl
2023-06-01 17:30 ` Gary Guo
2023-06-01 17:52 ` Martin Rodriguez Reboredo
2023-06-02 8:32 ` Alice Ryhl
2023-06-02 14:46 ` Andreas Hindborg (Samsung)
2023-06-11 15:49 ` Benno Lossin
2023-06-01 13:49 ` [PATCH v2 5/8] rust: workqueue: add helper for defining work_struct fields Alice Ryhl
2023-06-01 14:50 ` Martin Rodriguez Reboredo
2023-06-01 18:44 ` Boqun Feng
2023-06-02 8:38 ` Alice Ryhl
2023-06-02 16:32 ` Boqun Feng
2023-06-01 21:09 ` Boqun Feng
2023-06-02 9:37 ` Alice Ryhl
2023-06-02 14:41 ` Andreas Hindborg (Samsung)
2023-06-11 15:59 ` Benno Lossin
2023-06-27 8:42 ` Alice Ryhl
2023-06-01 13:49 ` [PATCH v2 6/8] rust: workqueue: implement `WorkItemPointer` for pointer types Alice Ryhl
2023-06-01 14:51 ` Martin Rodriguez Reboredo
2023-06-02 14:42 ` Andreas Hindborg (Samsung)
2023-06-11 16:01 ` Benno Lossin
2023-06-01 13:49 ` [PATCH v2 7/8] rust: workqueue: add `try_spawn` helper method Alice Ryhl
2023-06-01 14:53 ` Martin Rodriguez Reboredo
2023-06-02 14:43 ` Andreas Hindborg (Samsung)
2023-06-11 16:10 ` Benno Lossin
2023-06-01 13:49 ` [PATCH v2 8/8] rust: workqueue: add examples Alice Ryhl
2023-06-01 14:58 ` Martin Rodriguez Reboredo
2023-06-01 17:32 ` Gary Guo
2023-06-02 9:39 ` Alice Ryhl
2023-06-02 14:44 ` Andreas Hindborg (Samsung)
2023-06-02 14:48 ` Andreas Hindborg (Samsung)
2023-06-11 16:15 ` Benno Lossin
2023-06-27 8:38 ` Alice Ryhl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87o7ly0vxc.fsf@metaspace.dk \
--to=nmi@metaspace.dk \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=jiangshanlai@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=patches@lists.linux.dev \
--cc=rust-for-linux@vger.kernel.org \
--cc=tj@kernel.org \
--cc=wedsonaf@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.