summaryrefslogtreecommitdiffstats
path: root/rust/kernel/lib.rs
diff options
context:
space:
mode:
authorAlice Ryhl <aliceryhl@google.com>2023-08-28 12:48:04 +0200
committerTejun Heo <tj@kernel.org>2023-09-25 21:46:42 +0200
commit7324b88975c525a013ae0db747df97924ce80675 (patch)
treeafa7347e3fa89aa37ba897a53b42bf7ff2bc79f6 /rust/kernel/lib.rs
parentrust: workqueue: define built-in queues (diff)
downloadlinux-7324b88975c525a013ae0db747df97924ce80675.tar.xz
linux-7324b88975c525a013ae0db747df97924ce80675.zip
rust: workqueue: add helper for defining work_struct fields
The main challenge with defining `work_struct` fields is making sure that the function pointer stored in the `work_struct` is appropriate for the work item type it is embedded in. It needs to know the offset of the `work_struct` field being used (even if there are several!) so that it can do a `container_of`, and it needs to know the type of the work item so that it can call into the right user-provided code. All of this needs to happen in a way that provides a safe API to the user, so that users of the workqueue cannot mix up the function pointers. There are three important pieces that are relevant when doing this: * The pointer type. * The work item struct. This is what the pointer points at. * The `work_struct` field. This is a field of the work item struct. This patch introduces a separate trait for each piece. The pointer type is given a `WorkItemPointer` trait, which pointer types need to implement to be usable with the workqueue. This trait will be implemented for `Arc` and `Box` in a later patch in this patchset. Implementing this trait is unsafe because this is where the `container_of` operation happens, but user-code will not need to implement it themselves. The work item struct should then implement the `WorkItem` trait. This trait is where user-code specifies what they want to happen when a work item is executed. It also specifies what the correct pointer type is. Finally, to make the work item struct know the offset of its `work_struct` field, we use a trait called `HasWork<T, ID>`. If a type implements this trait, then the type declares that, at the given offset, there is a field of type `Work<T, ID>`. The trait is marked unsafe because the OFFSET constant must be correct, but we provide an `impl_has_work!` macro that can safely implement `HasWork<T>` on a type. The macro expands to something that only compiles if the specified field really has the type `Work<T>`. It is used like this: ``` struct MyWorkItem { work_field: Work<MyWorkItem, 1>, } impl_has_work! { impl HasWork<MyWorkItem, 1> for MyWorkItem { self.work_field } } ``` Note that since the `Work` type is annotated with an id, you can have several `work_struct` fields by using a different id for each one. 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: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com> Reviewed-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'rust/kernel/lib.rs')
-rw-r--r--rust/kernel/lib.rs1
1 files changed, 1 insertions, 0 deletions
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index d3b98b867a5e..e6aff80b521f 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -16,6 +16,7 @@
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![feature(new_uninit)]
+#![feature(offset_of)]
#![feature(ptr_metadata)]
#![feature(receiver_trait)]
#![feature(unsize)]