xref: /linux/drivers/android/binder/node/wrapper.rs (revision 148ab873d8194cb44f29474da3b4428fa2e100d1)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Copyright (C) 2025 Google LLC.
4 
5 use kernel::{list::ListArc, prelude::*, seq_file::SeqFile, seq_print, sync::UniqueArc};
6 
7 use crate::{node::Node, thread::Thread, BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead};
8 
9 use core::mem::MaybeUninit;
10 
11 pub(crate) struct CritIncrWrapper {
12     inner: UniqueArc<MaybeUninit<DTRWrap<NodeWrapper>>>,
13 }
14 
15 impl CritIncrWrapper {
16     pub(crate) fn new() -> Result<Self> {
17         Ok(CritIncrWrapper {
18             inner: UniqueArc::new_uninit(GFP_KERNEL)?,
19         })
20     }
21 
22     pub(super) fn init(self, node: DArc<Node>) -> DLArc<dyn DeliverToRead> {
23         match self.inner.pin_init_with(DTRWrap::new(NodeWrapper { node })) {
24             Ok(initialized) => ListArc::from(initialized) as DLArc<dyn DeliverToRead>,
25             Err(err) => match err {},
26         }
27     }
28 }
29 
30 struct NodeWrapper {
31     node: DArc<Node>,
32 }
33 
34 kernel::list::impl_list_arc_safe! {
35     impl ListArcSafe<0> for NodeWrapper {
36         untracked;
37     }
38 }
39 
40 impl DeliverToRead for NodeWrapper {
41     fn do_work(
42         self: DArc<Self>,
43         _thread: &Thread,
44         writer: &mut BinderReturnWriter<'_>,
45     ) -> Result<bool> {
46         let node = &self.node;
47         let mut owner_inner = node.owner.inner.lock();
48         let inner = node.inner.access_mut(&mut owner_inner);
49 
50         let ds = &mut inner.delivery_state;
51 
52         assert!(ds.has_pushed_wrapper);
53         assert!(ds.has_strong_zero2one);
54         ds.has_pushed_wrapper = false;
55         ds.has_strong_zero2one = false;
56 
57         node.do_work_locked(writer, owner_inner)
58     }
59 
60     fn cancel(self: DArc<Self>) {
61         let _drop_outside_lock;
62         let node = &self.node;
63         let mut owner_inner = node.owner.inner.lock();
64 
65         // We only do something on BINDER_THREAD_EXIT, not process exit.
66         if owner_inner.is_dead {
67             return;
68         }
69 
70         // We transfer the responsibility of the node refcount update to the scheduled Node because
71         // NodeWrapper has no way to re-create the ListArc.
72         let inner = node.inner.access_mut(&mut owner_inner);
73 
74         let ds = &mut inner.delivery_state;
75         assert!(ds.has_pushed_wrapper);
76         assert!(ds.has_strong_zero2one);
77         ds.has_pushed_wrapper = false;
78 
79         // We are changing the state to one where the Node is the strong zero2one update instead of
80         // the wrapper.
81         ds.has_weak_zero2one = false;
82 
83         if !ds.has_pushed_node {
84             if let Some(node2) = ListArc::try_from_arc_borrow(node.as_arc_borrow()) {
85                 ds.has_pushed_node = true;
86                 _drop_outside_lock = owner_inner.push_work(&node.owner, node2);
87             } else {
88                 // This can't actually happen.
89                 ds.has_strong_zero2one = false;
90             }
91         }
92     }
93 
94     fn should_sync_wakeup(&self) -> bool {
95         false
96     }
97 
98     #[inline(never)]
99     fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
100         seq_print!(
101             m,
102             "{}node work {}: u{:016x} c{:016x}\n",
103             prefix,
104             self.node.debug_id,
105             self.node.ptr,
106             self.node.cookie,
107         );
108         Ok(())
109     }
110 }
111