rust: workqueue: add examples

This adds two examples of how to use the workqueue. The first example
shows how to use it when you only have one `work_struct` field, and the
second example shows how to use it when you have multiple `work_struct`
fields.

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Reviewed-by: "Andreas Hindborg (Samsung)" <nmi@metaspace.dk>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Alice Ryhl 2023-08-28 10:48:07 +00:00 committed by Tejun Heo
parent 115c95e9e1
commit 15b286d1fd

View file

@ -26,6 +26,112 @@
//! * The `WorkItemPointer` trait is implemented for the pointer type that points at a something
//! that implements `WorkItem`.
//!
//! ## Example
//!
//! This example defines a struct that holds an integer and can be scheduled on the workqueue. When
//! the struct is executed, it will print the integer. Since there is only one `work_struct` field,
//! we do not need to specify ids for the fields.
//!
//! ```
//! use kernel::prelude::*;
//! use kernel::sync::Arc;
//! use kernel::workqueue::{self, Work, WorkItem};
//! use kernel::{impl_has_work, new_work};
//!
//! #[pin_data]
//! struct MyStruct {
//! value: i32,
//! #[pin]
//! work: Work<MyStruct>,
//! }
//!
//! impl_has_work! {
//! impl HasWork<Self> for MyStruct { self.work }
//! }
//!
//! impl MyStruct {
//! fn new(value: i32) -> Result<Arc<Self>> {
//! Arc::pin_init(pin_init!(MyStruct {
//! value,
//! work <- new_work!("MyStruct::work"),
//! }))
//! }
//! }
//!
//! impl WorkItem for MyStruct {
//! type Pointer = Arc<MyStruct>;
//!
//! fn run(this: Arc<MyStruct>) {
//! pr_info!("The value is: {}", this.value);
//! }
//! }
//!
//! /// This method will enqueue the struct for execution on the system workqueue, where its value
//! /// will be printed.
//! fn print_later(val: Arc<MyStruct>) {
//! let _ = workqueue::system().enqueue(val);
//! }
//! ```
//!
//! The following example shows how multiple `work_struct` fields can be used:
//!
//! ```
//! use kernel::prelude::*;
//! use kernel::sync::Arc;
//! use kernel::workqueue::{self, Work, WorkItem};
//! use kernel::{impl_has_work, new_work};
//!
//! #[pin_data]
//! struct MyStruct {
//! value_1: i32,
//! value_2: i32,
//! #[pin]
//! work_1: Work<MyStruct, 1>,
//! #[pin]
//! work_2: Work<MyStruct, 2>,
//! }
//!
//! impl_has_work! {
//! impl HasWork<Self, 1> for MyStruct { self.work_1 }
//! impl HasWork<Self, 2> for MyStruct { self.work_2 }
//! }
//!
//! impl MyStruct {
//! fn new(value_1: i32, value_2: i32) -> Result<Arc<Self>> {
//! Arc::pin_init(pin_init!(MyStruct {
//! value_1,
//! value_2,
//! work_1 <- new_work!("MyStruct::work_1"),
//! work_2 <- new_work!("MyStruct::work_2"),
//! }))
//! }
//! }
//!
//! impl WorkItem<1> for MyStruct {
//! type Pointer = Arc<MyStruct>;
//!
//! fn run(this: Arc<MyStruct>) {
//! pr_info!("The value is: {}", this.value_1);
//! }
//! }
//!
//! impl WorkItem<2> for MyStruct {
//! type Pointer = Arc<MyStruct>;
//!
//! fn run(this: Arc<MyStruct>) {
//! pr_info!("The second value is: {}", this.value_2);
//! }
//! }
//!
//! fn print_1_later(val: Arc<MyStruct>) {
//! let _ = workqueue::system().enqueue::<Arc<MyStruct>, 1>(val);
//! }
//!
//! fn print_2_later(val: Arc<MyStruct>) {
//! let _ = workqueue::system().enqueue::<Arc<MyStruct>, 2>(val);
//! }
//! ```
//!
//! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h)
use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};