diff options
Diffstat (limited to 'rust/kernel/workqueue.rs')
| -rw-r--r-- | rust/kernel/workqueue.rs | 54 | 
1 files changed, 28 insertions, 26 deletions
| diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 480cb292e7c2..1cec63a2aea8 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -33,7 +33,6 @@  //! we do not need to specify ids for the fields.  //!  //! ``` -//! use kernel::prelude::*;  //! use kernel::sync::Arc;  //! use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};  //! @@ -53,7 +52,7 @@  //!         Arc::pin_init(pin_init!(MyStruct {  //!             value,  //!             work <- new_work!("MyStruct::work"), -//!         })) +//!         }), GFP_KERNEL)  //!     }  //! }  //! @@ -75,7 +74,6 @@  //! The following example shows how multiple `work_struct` fields can be used:  //!  //! ``` -//! use kernel::prelude::*;  //! use kernel::sync::Arc;  //! use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};  //! @@ -101,7 +99,7 @@  //!             value_2,  //!             work_1 <- new_work!("MyStruct::work_1"),  //!             work_2 <- new_work!("MyStruct::work_2"), -//!         })) +//!         }), GFP_KERNEL)  //!     }  //! }  //! @@ -132,11 +130,9 @@  //!  //! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h) -use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque}; -use alloc::alloc::AllocError; -use alloc::boxed::Box; +use crate::alloc::{AllocError, Flags}; +use crate::{prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};  use core::marker::PhantomData; -use core::pin::Pin;  /// Creates a [`Work`] initialiser with the given name and a newly-created lock class.  #[macro_export] @@ -210,13 +206,17 @@ impl Queue {      /// Tries to spawn the given function or closure as a work item.      ///      /// This method can fail because it allocates memory to store the work item. -    pub fn try_spawn<T: 'static + Send + FnOnce()>(&self, func: T) -> Result<(), AllocError> { +    pub fn try_spawn<T: 'static + Send + FnOnce()>( +        &self, +        flags: Flags, +        func: T, +    ) -> Result<(), AllocError> {          let init = pin_init!(ClosureWork {              work <- new_work!("Queue::try_spawn"),              func: Some(func),          }); -        self.enqueue(Box::pin_init(init).map_err(|_| AllocError)?); +        self.enqueue(Box::pin_init(init, flags).map_err(|_| AllocError)?);          Ok(())      }  } @@ -346,8 +346,10 @@ pub trait WorkItem<const ID: u64 = 0> {  /// This is a helper type used to associate a `work_struct` with the [`WorkItem`] that uses it.  ///  /// [`run`]: WorkItemPointer::run +#[pin_data]  #[repr(transparent)]  pub struct Work<T: ?Sized, const ID: u64 = 0> { +    #[pin]      work: Opaque<bindings::work_struct>,      _inner: PhantomData<T>,  } @@ -369,21 +371,22 @@ impl<T: ?Sized, const ID: u64> Work<T, ID> {      where          T: WorkItem<ID>,      { -        // SAFETY: The `WorkItemPointer` implementation promises that `run` can be used as the work -        // item function. -        unsafe { -            kernel::init::pin_init_from_closure(move |slot| { -                let slot = Self::raw_get(slot); -                bindings::init_work_with_key( -                    slot, -                    Some(T::Pointer::run), -                    false, -                    name.as_char_ptr(), -                    key.as_ptr(), -                ); -                Ok(()) -            }) -        } +        pin_init!(Self { +            work <- Opaque::ffi_init(|slot| { +                // SAFETY: The `WorkItemPointer` implementation promises that `run` can be used as +                // the work item function. +                unsafe { +                    bindings::init_work_with_key( +                        slot, +                        Some(T::Pointer::run), +                        false, +                        name.as_char_ptr(), +                        key.as_ptr(), +                    ) +                } +            }), +            _inner: PhantomData, +        })      }      /// Get a pointer to the inner `work_struct`. @@ -408,7 +411,6 @@ impl<T: ?Sized, const ID: u64> Work<T, ID> {  /// like this:  ///  /// ```no_run -/// use kernel::prelude::*;  /// use kernel::workqueue::{impl_has_work, Work};  ///  /// struct MyWorkItem { |