Skip to content

Commit a355755

Browse files
committed
added pinned_drop
1 parent fef97c6 commit a355755

File tree

4 files changed

+125
-3
lines changed

4 files changed

+125
-3
lines changed

drivers/android/transaction.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use kernel::{
77
io_buffer::IoBufferWriter,
88
linked_list::List,
99
linked_list::{GetLinks, Links},
10+
macros::pinned_drop,
1011
new_spinlock,
1112
prelude::*,
1213
sync::{Arc, SpinLock, UniqueArc},
@@ -27,7 +28,7 @@ struct TransactionInner {
2728
file_list: List<Box<FileInfo>>,
2829
}
2930

30-
#[pin_project]
31+
#[pin_project(PinnedDrop)]
3132
pub(crate) struct Transaction {
3233
#[pin]
3334
inner: SpinLock<TransactionInner>,
@@ -276,8 +277,9 @@ impl DeliverToRead for Transaction {
276277
}
277278
}
278279

279-
impl Drop for Transaction {
280-
fn drop(&mut self) {
280+
#[pinned_drop]
281+
impl PinnedDrop for Transaction {
282+
fn drop(self: Pin<&mut Self>) {
281283
if self.free_allocation.load(Ordering::Relaxed) {
282284
self.to.buffer_get(self.data_address);
283285
}

rust/kernel/init.rs

+12
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,18 @@ where
641641
}
642642
}
643643

644+
/// Trait facilitating pinned destruction.
645+
///
646+
/// Use [`pinned_drop`] to implement this trait safely.
647+
pub unsafe trait PinnedDrop {
648+
/// # Safety
649+
///
650+
/// Only call this from `<Self as Drop>::drop`.
651+
unsafe fn drop(self: Pin<&mut Self>);
652+
#[doc(hidden)]
653+
fn __ensure_no_unsafe_op_in_drop(self: Pin<&mut Self>);
654+
}
655+
644656
/// Smart pointer that can initialize memory in-place.
645657
pub trait InPlaceInit<T>: Sized {
646658
/// Use the given initializer to in-place initialize a `T`.

rust/macros/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod concat_idents;
66
mod helpers;
77
mod module;
88
mod pin_project;
9+
mod pinned_drop;
910
mod vtable;
1011

1112
use proc_macro::TokenStream;
@@ -211,3 +212,9 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream {
211212
pub fn pin_project(inner: TokenStream, item: TokenStream) -> TokenStream {
212213
pin_project::pin_project(inner, item)
213214
}
215+
216+
/// TODO
217+
#[proc_macro_attribute]
218+
pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
219+
pinned_drop::pinned_drop(args, input)
220+
}

rust/macros/pinned_drop.rs

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
4+
5+
pub(crate) fn pinned_drop(_args: TokenStream, input: TokenStream) -> TokenStream {
6+
let mut toks = input.into_iter().collect::<Vec<_>>();
7+
assert!(!toks.is_empty());
8+
// ensure that we have an impl item
9+
assert!(matches!(&toks[0], TokenTree::Ident(i) if i.to_string() == "impl"));
10+
// ensure that we are implementing `PinnedDrop`
11+
let mut nesting: usize = 0;
12+
let mut pinned_drop_idx = None;
13+
for (i, tt) in toks.iter().enumerate() {
14+
match tt {
15+
TokenTree::Punct(p) if p.as_char() == '<' => {
16+
nesting += 1;
17+
}
18+
TokenTree::Punct(p) if p.as_char() == '>' => {
19+
nesting = nesting.checked_sub(1).unwrap();
20+
}
21+
_ => {}
22+
}
23+
if i >= 1 && nesting == 0 {
24+
assert!(matches!(tt, TokenTree::Ident(i) if i.to_string() == "PinnedDrop"));
25+
pinned_drop_idx = Some(i);
26+
break;
27+
}
28+
}
29+
let idx = pinned_drop_idx.unwrap();
30+
//inserting `::kernel::init::` in reverse order
31+
toks.insert(idx, TokenTree::Punct(Punct::new(':', Spacing::Alone)));
32+
toks.insert(idx, TokenTree::Punct(Punct::new(':', Spacing::Joint)));
33+
toks.insert(idx, TokenTree::Ident(Ident::new("init", Span::call_site())));
34+
toks.insert(idx, TokenTree::Punct(Punct::new(':', Spacing::Alone)));
35+
toks.insert(idx, TokenTree::Punct(Punct::new(':', Spacing::Joint)));
36+
toks.insert(
37+
idx,
38+
TokenTree::Ident(Ident::new("kernel", Span::call_site())),
39+
);
40+
toks.insert(idx, TokenTree::Punct(Punct::new(':', Spacing::Alone)));
41+
toks.insert(idx, TokenTree::Punct(Punct::new(':', Spacing::Joint)));
42+
if let Some(TokenTree::Group(last)) = toks.pop() {
43+
let mut inner = last.stream().into_iter().collect::<Vec<_>>();
44+
if let Some(TokenTree::Group(inner_last)) = inner.pop() {
45+
// make the impl unsafe
46+
toks.insert(0, TokenTree::Ident(Ident::new("unsafe", Span::call_site())));
47+
// make the first function unsafe
48+
inner.insert(0, TokenTree::Ident(Ident::new("unsafe", Span::call_site())));
49+
// re-add the body
50+
inner.push(TokenTree::Group(inner_last.clone()));
51+
add_ensure_no_unsafe_op_in_drop(&mut inner, inner_last);
52+
toks.push(TokenTree::Group(Group::new(
53+
Delimiter::Brace,
54+
TokenStream::from_iter(inner),
55+
)));
56+
TokenStream::from_iter(toks)
57+
} else {
58+
toks.push(TokenTree::Group(last));
59+
TokenStream::from_iter(toks)
60+
}
61+
} else {
62+
TokenStream::from_iter(toks)
63+
}
64+
}
65+
66+
fn add_ensure_no_unsafe_op_in_drop(v: &mut Vec<TokenTree>, inner_last: Group) {
67+
v.push(TokenTree::Ident(Ident::new("fn", Span::call_site())));
68+
v.push(TokenTree::Ident(Ident::new(
69+
"__ensure_no_unsafe_op_in_drop",
70+
Span::call_site(),
71+
)));
72+
v.push(TokenTree::Group(Group::new(
73+
Delimiter::Parenthesis,
74+
TokenStream::from_iter(vec![
75+
TokenTree::Ident(Ident::new("self", Span::call_site())),
76+
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
77+
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
78+
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
79+
TokenTree::Ident(Ident::new("core", Span::call_site())),
80+
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
81+
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
82+
TokenTree::Ident(Ident::new("pin", Span::call_site())),
83+
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
84+
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
85+
TokenTree::Ident(Ident::new("Pin", Span::call_site())),
86+
TokenTree::Punct(Punct::new('<', Spacing::Alone)),
87+
TokenTree::Punct(Punct::new('&', Spacing::Alone)),
88+
TokenTree::Ident(Ident::new("mut", Span::call_site())),
89+
TokenTree::Ident(Ident::new("Self", Span::call_site())),
90+
TokenTree::Punct(Punct::new('>', Spacing::Alone)),
91+
]),
92+
)));
93+
v.push(TokenTree::Group(Group::new(
94+
Delimiter::Brace,
95+
TokenStream::from_iter(vec![
96+
TokenTree::Ident(Ident::new("if", Span::call_site())),
97+
TokenTree::Ident(Ident::new("false", Span::call_site())),
98+
TokenTree::Group(inner_last),
99+
]),
100+
)));
101+
}

0 commit comments

Comments
 (0)