From b03917e02bf9861be887a7e67c399b3b014f88be Mon Sep 17 00:00:00 2001 From: Konstantin Andrikopoulos Date: Wed, 27 Nov 2024 15:07:38 +0000 Subject: rust: add safety comment in workqueue traits Add missing safety comments for the implementation of the unsafe traits WorkItemPointer and RawWorkItem for Arc in workqueue.rs Link: https://github.com/Rust-for-Linux/linux/issues/351. Co-developed-by: Vangelis Mamalakis Signed-off-by: Vangelis Mamalakis Suggested-by: Miguel Ojeda Reviewed-by: Alice Ryhl Signed-off-by: Konstantin Andrikopoulos Signed-off-by: Tejun Heo --- rust/kernel/workqueue.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'rust/kernel/workqueue.rs') diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 4d1d2062f6eb..fd3e97192ed8 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -519,7 +519,15 @@ impl_has_work! { impl{T} HasWork for ClosureWork { self.work } } -// SAFETY: TODO. +// SAFETY: The `__enqueue` implementation in RawWorkItem uses a `work_struct` initialized with the +// `run` method of this trait as the function pointer because: +// - `__enqueue` gets the `work_struct` from the `Work` field, using `T::raw_get_work`. +// - The only safe way to create a `Work` object is through `Work::new`. +// - `Work::new` makes sure that `T::Pointer::run` is passed to `init_work_with_key`. +// - Finally `Work` and `RawWorkItem` guarantee that the correct `Work` field +// will be used because of the ID const generic bound. This makes sure that `T::raw_get_work` +// uses the correct offset for the `Work` field, and `Work::new` picks the correct +// implementation of `WorkItemPointer` for `Arc`. unsafe impl WorkItemPointer for Arc where T: WorkItem, @@ -537,7 +545,13 @@ where } } -// SAFETY: TODO. +// SAFETY: The `work_struct` raw pointer is guaranteed to be valid for the duration of the call to +// the closure because we get it from an `Arc`, which means that the ref count will be at least 1, +// and we don't drop the `Arc` ourselves. If `queue_work_on` returns true, it is further guaranteed +// to be valid until a call to the function pointer in `work_struct` because we leak the memory it +// points to, and only reclaim it if the closure returns false, or in `WorkItemPointer::run`, which +// is what the function pointer in the `work_struct` must be pointing to, according to the safety +// requirements of `WorkItemPointer`. unsafe impl RawWorkItem for Arc where T: WorkItem, -- cgit v1.2.3 From 3f4223c007b25327c49aabe3af8ecc72bb33dbf6 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Wed, 16 Oct 2024 15:35:07 +0200 Subject: rust: workqueue: Enable execution of doctests Having the Rust doctests enabled these workqueue tests are built but not executed as the final callers of the print_*() functions are missing. Add them. The result is # rust_doctest_kernel_workqueue_rs_0.location: rust/kernel/workqueue.rs:35 rust_doctests_kernel: The value is: 42 ok 94 rust_doctest_kernel_workqueue_rs_0 # rust_doctest_kernel_workqueue_rs_3.location: rust/kernel/workqueue.rs:78 rust_doctests_kernel: The value is: 24 rust_doctests_kernel: The second value is: 42 ok 97 rust_doctest_kernel_workqueue_rs_3 Without this change the "The value ..." outputs are not there meaning that this test code is not run. Reviewed-by: Alice Ryhl Signed-off-by: Dirk Behme Reviewed-by: Boqun Feng Acked-by: Tejun Heo Link: https://lore.kernel.org/r/cb953202-0dbe-4127-8a8e-6a75258c2116@gmail.com [ Reworded slightly. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/workqueue.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'rust/kernel/workqueue.rs') diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 4d1d2062f6eb..1dcd53478edd 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -69,6 +69,7 @@ //! fn print_later(val: Arc) { //! let _ = workqueue::system().enqueue(val); //! } +//! # print_later(MyStruct::new(42).unwrap()); //! ``` //! //! The following example shows how multiple `work_struct` fields can be used: @@ -126,6 +127,8 @@ //! fn print_2_later(val: Arc) { //! let _ = workqueue::system().enqueue::, 2>(val); //! } +//! # print_1_later(MyStruct::new(24, 25).unwrap()); +//! # print_2_later(MyStruct::new(41, 42).unwrap()); //! ``` //! //! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h) -- cgit v1.2.3