Skip to content

Commit 5175f1b

Browse files
committed
rust: Added pinned-init API
This API is used to initialize pinned structs. TODO: describe the purpose and functionality of the API better. Also added `pin_init` to `Arc`. Also added `pin_data` attribute macro Also added `pin_init`, `init` and `pin_data` to the prelude. This is a convenience attribute macro that can be used instead of ``` pin_data! { Struct { field: u8, // ... } } ``` Signed-off-by: Benno Lossin <[email protected]>
1 parent 441712c commit 5175f1b

File tree

9 files changed

+1445
-2
lines changed

9 files changed

+1445
-2
lines changed

rust/kernel/init.rs

+790
Large diffs are not rendered by default.

rust/kernel/init/__private.rs

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Workaround for specialization
4+
5+
use super::*;
6+
7+
mod sealed {
8+
use super::*;
9+
pub trait Sealed {}
10+
11+
impl Sealed for Direct {}
12+
impl Sealed for Closure {}
13+
}
14+
15+
pub trait InitWay: sealed::Sealed {}
16+
17+
impl InitWay for Direct {}
18+
impl InitWay for Closure {}
19+
20+
pub struct Direct;
21+
pub struct Closure;
22+
23+
/// # Safety
24+
/// Same as [`PinInit`]
25+
pub unsafe trait __PinInitImpl<T: ?Sized, E, W: InitWay> {
26+
/// # Safety
27+
/// Same as [`PinInit::__pinned_init`]
28+
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>;
29+
}
30+
31+
/// # Safety
32+
/// Same as [`Init`]
33+
pub unsafe trait __InitImpl<T: ?Sized, E, W: InitWay>: __PinInitImpl<T, E, W> {
34+
/// # Safety
35+
/// Same as [`Init::__init`]
36+
unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
37+
}
38+
39+
/// # Safety
40+
/// Only implemented by pin_data!
41+
pub unsafe trait __PinData {
42+
type __PinData;
43+
}
44+
45+
unsafe impl<T> __PinInitImpl<T, Infallible, Direct> for T {
46+
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> {
47+
// SAFETY: pointer valid as per function contract
48+
unsafe { slot.write(self) };
49+
Ok(())
50+
}
51+
}
52+
53+
unsafe impl<T> __InitImpl<T, Infallible, Direct> for T {
54+
unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> {
55+
// SAFETY: pointer valid as per function contract
56+
unsafe { slot.write(self) };
57+
Ok(())
58+
}
59+
}
60+
61+
unsafe impl<I, T, E> __InitImpl<T, E, Closure> for I
62+
where
63+
I: Init<T, E>,
64+
{
65+
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
66+
unsafe { Init::__init(self, slot) }
67+
}
68+
}
69+
70+
unsafe impl<I, T, E> __PinInitImpl<T, E, Closure> for I
71+
where
72+
I: PinInit<T, E>,
73+
{
74+
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
75+
unsafe { PinInit::__pinned_init(self, slot) }
76+
}
77+
}
78+
79+
/// When a value of this type is dropped, it drops something else.
80+
pub struct DropGuard<T: ?Sized>(*mut T);
81+
82+
impl<T: ?Sized> DropGuard<T> {
83+
/// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped.
84+
///
85+
/// # Safety
86+
/// `ptr` must be a valid poiner.
87+
///
88+
/// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`:
89+
/// - has not been dropped,
90+
/// - is not accesible by any other means,
91+
/// - will not be dropped by any other means.
92+
pub unsafe fn new(ptr: *mut T) -> Self {
93+
Self(ptr)
94+
}
95+
}
96+
97+
impl<T: ?Sized> Drop for DropGuard<T> {
98+
fn drop(&mut self) {
99+
// SAFETY: safe as a `DropGuard` can only be constructed using the unsafe new function.
100+
unsafe { ptr::drop_in_place(self.0) }
101+
}
102+
}
103+
104+
/// Stack initializer helper type. See [`stack_init`].
105+
pub struct StackInit<T>(MaybeUninit<T>, bool);
106+
107+
impl<T> Drop for StackInit<T> {
108+
fn drop(&mut self) {
109+
if self.1 {
110+
unsafe { self.0.assume_init_drop() };
111+
}
112+
}
113+
}
114+
impl<T> StackInit<T> {
115+
pub fn uninit() -> Self {
116+
Self(MaybeUninit::uninit(), false)
117+
}
118+
119+
/// # Safety
120+
/// The caller ensures that `self` is on the stack and not accesible to **any** other code.
121+
pub unsafe fn init<E>(&mut self, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> {
122+
unsafe { init.__pinned_init(self.0.as_mut_ptr()) }?;
123+
self.1 = true;
124+
Ok(unsafe { Pin::new_unchecked(self.0.assume_init_mut()) })
125+
}
126+
}

0 commit comments

Comments
 (0)