diff options
Diffstat (limited to 'rust/macros/lib.rs')
-rw-r--r-- | rust/macros/lib.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index c1d385e345b9..3fc74cb4ea19 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -2,9 +2,13 @@ //! Crate for all kernel procedural macros. +#[macro_use] +mod quote; mod concat_idents; mod helpers; mod module; +mod pin_data; +mod pinned_drop; mod vtable; use proc_macro::TokenStream; @@ -166,3 +170,79 @@ pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { pub fn concat_idents(ts: TokenStream) -> TokenStream { concat_idents::concat_idents(ts) } + +/// Used to specify the pinning information of the fields of a struct. +/// +/// This is somewhat similar in purpose as +/// [pin-project-lite](https://crates.io/crates/pin-project-lite). +/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each +/// field you want to structurally pin. +/// +/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`, +/// then `#[pin]` directs the type of initializer that is required. +/// +/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this +/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with +/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care. +/// +/// # Examples +/// +/// ```rust,ignore +/// #[pin_data] +/// struct DriverData { +/// #[pin] +/// queue: Mutex<Vec<Command>>, +/// buf: Box<[u8; 1024 * 1024]>, +/// } +/// ``` +/// +/// ```rust,ignore +/// #[pin_data(PinnedDrop)] +/// struct DriverData { +/// #[pin] +/// queue: Mutex<Vec<Command>>, +/// buf: Box<[u8; 1024 * 1024]>, +/// raw_info: *mut Info, +/// } +/// +/// #[pinned_drop] +/// impl PinnedDrop for DriverData { +/// fn drop(self: Pin<&mut Self>) { +/// unsafe { bindings::destroy_info(self.raw_info) }; +/// } +/// } +/// ``` +/// +/// [`pin_init!`]: ../kernel/macro.pin_init.html +// ^ cannot use direct link, since `kernel` is not a dependency of `macros`. +#[proc_macro_attribute] +pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream { + pin_data::pin_data(inner, item) +} + +/// Used to implement `PinnedDrop` safely. +/// +/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`. +/// +/// # Examples +/// +/// ```rust,ignore +/// #[pin_data(PinnedDrop)] +/// struct DriverData { +/// #[pin] +/// queue: Mutex<Vec<Command>>, +/// buf: Box<[u8; 1024 * 1024]>, +/// raw_info: *mut Info, +/// } +/// +/// #[pinned_drop] +/// impl PinnedDrop for DriverData { +/// fn drop(self: Pin<&mut Self>) { +/// unsafe { bindings::destroy_info(self.raw_info) }; +/// } +/// } +/// ``` +#[proc_macro_attribute] +pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { + pinned_drop::pinned_drop(args, input) +} |