|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | + |
| 3 | +//! Extensions to the [`pin-init`] crate. |
| 4 | +//! |
| 5 | +//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential |
| 6 | +//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move. |
| 7 | +//! |
| 8 | +//! The [`pin-init`] crate is the way such structs are initialized on the Rust side. Please refer |
| 9 | +//! to its documentation to better understand how to use it. Additionally, there are many examples |
| 10 | +//! throughout the kernel, such as the types from the [`sync`] module. And the ones presented |
| 11 | +//! below. |
| 12 | +//! |
| 13 | +//! [`sync`]: crate::sync |
| 14 | +//! [pinning]: https://doc.rust-lang.org/std/pin/index.html |
| 15 | +//! [`pin-init`]: https://rust.docs.kernel.org/pin_init/ |
| 16 | +//! |
| 17 | +//! # [`Opaque<T>`] |
| 18 | +//! |
| 19 | +//! For the special case where initializing a field is a single FFI-function call that cannot fail, |
| 20 | +//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single |
| 21 | +//! [`Opaque<T>`] field by just delegating to the supplied closure. You can use these in |
| 22 | +//! combination with [`pin_init!`]. |
| 23 | +//! |
| 24 | +//! [`Opaque<T>`]: crate::types::Opaque |
| 25 | +//! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init |
| 26 | +//! [`pin_init!`]: crate::pin_init |
| 27 | +//! |
| 28 | +//! # Examples |
| 29 | +//! |
| 30 | +//! ## General Examples |
| 31 | +//! |
| 32 | +//! ```rust,ignore |
| 33 | +//! # #![allow(clippy::disallowed_names)] |
| 34 | +//! use kernel::types::Opaque; |
| 35 | +//! use pin_init::pin_init_from_closure; |
| 36 | +//! |
| 37 | +//! // assume we have some `raw_foo` type in C: |
| 38 | +//! #[repr(C)] |
| 39 | +//! struct RawFoo([u8; 16]); |
| 40 | +//! extern { |
| 41 | +//! fn init_foo(_: *mut RawFoo); |
| 42 | +//! } |
| 43 | +//! |
| 44 | +//! #[pin_data] |
| 45 | +//! struct Foo { |
| 46 | +//! #[pin] |
| 47 | +//! raw: Opaque<RawFoo>, |
| 48 | +//! } |
| 49 | +//! |
| 50 | +//! impl Foo { |
| 51 | +//! fn setup(self: Pin<&mut Self>) { |
| 52 | +//! pr_info!("Setting up foo"); |
| 53 | +//! } |
| 54 | +//! } |
| 55 | +//! |
| 56 | +//! let foo = pin_init!(Foo { |
| 57 | +//! raw <- unsafe { |
| 58 | +//! Opaque::ffi_init(|s| { |
| 59 | +//! // note that this cannot fail. |
| 60 | +//! init_foo(s); |
| 61 | +//! }) |
| 62 | +//! }, |
| 63 | +//! }).pin_chain(|foo| { |
| 64 | +//! foo.setup(); |
| 65 | +//! Ok(()) |
| 66 | +//! }); |
| 67 | +//! ``` |
| 68 | +//! |
| 69 | +//! ```rust,ignore |
| 70 | +//! # #![allow(unreachable_pub, clippy::disallowed_names)] |
| 71 | +//! use kernel::{prelude::*, types::Opaque}; |
| 72 | +//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin}; |
| 73 | +//! # mod bindings { |
| 74 | +//! # #![allow(non_camel_case_types)] |
| 75 | +//! # pub struct foo; |
| 76 | +//! # pub unsafe fn init_foo(_ptr: *mut foo) {} |
| 77 | +//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {} |
| 78 | +//! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 } |
| 79 | +//! # } |
| 80 | +//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround. |
| 81 | +//! # trait FromErrno { |
| 82 | +//! # fn from_errno(errno: core::ffi::c_int) -> Error { |
| 83 | +//! # // Dummy error that can be constructed outside the `kernel` crate. |
| 84 | +//! # Error::from(core::fmt::Error) |
| 85 | +//! # } |
| 86 | +//! # } |
| 87 | +//! # impl FromErrno for Error {} |
| 88 | +//! /// # Invariants |
| 89 | +//! /// |
| 90 | +//! /// `foo` is always initialized |
| 91 | +//! #[pin_data(PinnedDrop)] |
| 92 | +//! pub struct RawFoo { |
| 93 | +//! #[pin] |
| 94 | +//! foo: Opaque<bindings::foo>, |
| 95 | +//! #[pin] |
| 96 | +//! _p: PhantomPinned, |
| 97 | +//! } |
| 98 | +//! |
| 99 | +//! impl RawFoo { |
| 100 | +//! pub fn new(flags: u32) -> impl PinInit<Self, Error> { |
| 101 | +//! // SAFETY: |
| 102 | +//! // - when the closure returns `Ok(())`, then it has successfully initialized and |
| 103 | +//! // enabled `foo`, |
| 104 | +//! // - when it returns `Err(e)`, then it has cleaned up before |
| 105 | +//! unsafe { |
| 106 | +//! pin_init::pin_init_from_closure(move |slot: *mut Self| { |
| 107 | +//! // `slot` contains uninit memory, avoid creating a reference. |
| 108 | +//! let foo = addr_of_mut!((*slot).foo); |
| 109 | +//! |
| 110 | +//! // Initialize the `foo` |
| 111 | +//! bindings::init_foo(Opaque::raw_get(foo)); |
| 112 | +//! |
| 113 | +//! // Try to enable it. |
| 114 | +//! let err = bindings::enable_foo(Opaque::raw_get(foo), flags); |
| 115 | +//! if err != 0 { |
| 116 | +//! // Enabling has failed, first clean up the foo and then return the error. |
| 117 | +//! bindings::destroy_foo(Opaque::raw_get(foo)); |
| 118 | +//! return Err(Error::from_errno(err)); |
| 119 | +//! } |
| 120 | +//! |
| 121 | +//! // All fields of `RawFoo` have been initialized, since `_p` is a ZST. |
| 122 | +//! Ok(()) |
| 123 | +//! }) |
| 124 | +//! } |
| 125 | +//! } |
| 126 | +//! } |
| 127 | +//! |
| 128 | +//! #[pinned_drop] |
| 129 | +//! impl PinnedDrop for RawFoo { |
| 130 | +//! fn drop(self: Pin<&mut Self>) { |
| 131 | +//! // SAFETY: Since `foo` is initialized, destroying is safe. |
| 132 | +//! unsafe { bindings::destroy_foo(self.foo.get()) }; |
| 133 | +//! } |
| 134 | +//! } |
| 135 | +//! ``` |
0 commit comments