rust/pin-init/README.md

Source file repositories/reference/linux-study-clean/rust/pin-init/README.md

File Facts

System
Linux kernel
Corpus path
rust/pin-init/README.md
Extension
.md
Size
9844 bytes
Lines
248
Domain
Rust Kernel Layer
Bucket
Rust API Membrane
Inferred role
Rust Kernel Layer: documentation
Status
atlas-only

Why This File Exists

Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.

Dependency Surface

Detected Declarations

Annotated Snippet

struct Foo {
    #[pin]
    a: CMutex<usize>,
    b: u32,
}

let foo = pin_init!(Foo {
    a <- CMutex::new(42),
    b: 24,
});
```

`foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
(or just the stack) to actually initialize a `Foo`:

```rust
let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);
```

For more information see the [`pin_init!`] macro.

### Using a custom function/macro that returns an initializer

Many types that use this library supply a function/macro that returns an initializer, because
the above method only works for types where you can access the fields.

```rust
let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
```

To declare an init macro/function you just return an [`impl PinInit<T, E>`]:

```rust
#[pin_data]
struct DriverData {
    #[pin]
    status: CMutex<i32>,
    buffer: Box<[u8; 1_000_000]>,
}

impl DriverData {
    fn new() -> impl PinInit<Self, Error> {
        pin_init!(Self {
            status <- CMutex::new(0),
            buffer: Box::init(pin_init::init_zeroed())?,
        }? Error)
    }
}
```

### Manual creation of an initializer

Often when working with primitives the previous approaches are not sufficient. That is where
[`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
[`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
actually does the initialization in the correct way. Here are the things to look out for
(we are calling the parameter to the closure `slot`):
- when the closure returns `Ok(())`, then it has completed the initialization successfully, so
  `slot` now contains a valid bit pattern for the type `T`,
- when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
  you need to take care to clean up anything if your initialization fails mid-way,
- you may assume that `slot` will stay pinned even after the closure returns until `drop` of
  `slot` gets called.

```rust
use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
use core::{
    marker::PhantomPinned,
    cell::UnsafeCell,
    pin::Pin,

Annotation

Implementation Notes