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