Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/android/binder/node.rs
29524 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
// Copyright (C) 2025 Google LLC.
4
5
use kernel::{
6
list::{AtomicTracker, List, ListArc, ListLinks, TryNewListArc},
7
prelude::*,
8
seq_file::SeqFile,
9
seq_print,
10
sync::lock::{spinlock::SpinLockBackend, Guard},
11
sync::{Arc, LockedBy, SpinLock},
12
};
13
14
use crate::{
15
defs::*,
16
error::BinderError,
17
process::{NodeRefInfo, Process, ProcessInner},
18
thread::Thread,
19
transaction::Transaction,
20
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
21
};
22
23
use core::mem;
24
25
mod wrapper;
26
pub(crate) use self::wrapper::CritIncrWrapper;
27
28
#[derive(Debug)]
29
pub(crate) struct CouldNotDeliverCriticalIncrement;
30
31
/// Keeps track of how this node is scheduled.
32
///
33
/// There are two ways to schedule a node to a work list. Just schedule the node itself, or
34
/// allocate a wrapper that references the node and schedule the wrapper. These wrappers exists to
35
/// make it possible to "move" a node from one list to another - when `do_work` is called directly
36
/// on the `Node`, then it's a no-op if there's also a pending wrapper.
37
///
38
/// Wrappers are generally only needed for zero-to-one refcount increments, and there are two cases
39
/// of this: weak increments and strong increments. We call such increments "critical" because it
40
/// is critical that they are delivered to the thread doing the increment. Some examples:
41
///
42
/// * One thread makes a zero-to-one strong increment, and another thread makes a zero-to-one weak
43
/// increment. Delivering the node to the thread doing the weak increment is wrong, since the
44
/// thread doing the strong increment may have ended a long time ago when the command is actually
45
/// processed by userspace.
46
///
47
/// * We have a weak reference and are about to drop it on one thread. But then another thread does
48
/// a zero-to-one strong increment. If the strong increment gets sent to the thread that was
49
/// about to drop the weak reference, then the strong increment could be processed after the
50
/// other thread has already exited, which would be too late.
51
///
52
/// Note that trying to create a `ListArc` to the node can succeed even if `has_normal_push` is
53
/// set. This is because another thread might just have popped the node from a todo list, but not
54
/// yet called `do_work`. However, if `has_normal_push` is false, then creating a `ListArc` should
55
/// always succeed.
56
///
57
/// Like the other fields in `NodeInner`, the delivery state is protected by the process lock.
58
struct DeliveryState {
59
/// Is the `Node` currently scheduled?
60
has_pushed_node: bool,
61
62
/// Is a wrapper currently scheduled?
63
///
64
/// The wrapper is used only for strong zero2one increments.
65
has_pushed_wrapper: bool,
66
67
/// Is the currently scheduled `Node` scheduled due to a weak zero2one increment?
68
///
69
/// Weak zero2one operations are always scheduled using the `Node`.
70
has_weak_zero2one: bool,
71
72
/// Is the currently scheduled wrapper/`Node` scheduled due to a strong zero2one increment?
73
///
74
/// If `has_pushed_wrapper` is set, then the strong zero2one increment was scheduled using the
75
/// wrapper. Otherwise, `has_pushed_node` must be set and it was scheduled using the `Node`.
76
has_strong_zero2one: bool,
77
}
78
79
impl DeliveryState {
80
fn should_normal_push(&self) -> bool {
81
!self.has_pushed_node && !self.has_pushed_wrapper
82
}
83
84
fn did_normal_push(&mut self) {
85
assert!(self.should_normal_push());
86
self.has_pushed_node = true;
87
}
88
89
fn should_push_weak_zero2one(&self) -> bool {
90
!self.has_weak_zero2one && !self.has_strong_zero2one
91
}
92
93
fn can_push_weak_zero2one_normally(&self) -> bool {
94
!self.has_pushed_node
95
}
96
97
fn did_push_weak_zero2one(&mut self) {
98
assert!(self.should_push_weak_zero2one());
99
assert!(self.can_push_weak_zero2one_normally());
100
self.has_pushed_node = true;
101
self.has_weak_zero2one = true;
102
}
103
104
fn should_push_strong_zero2one(&self) -> bool {
105
!self.has_strong_zero2one
106
}
107
108
fn can_push_strong_zero2one_normally(&self) -> bool {
109
!self.has_pushed_node
110
}
111
112
fn did_push_strong_zero2one(&mut self) {
113
assert!(self.should_push_strong_zero2one());
114
assert!(self.can_push_strong_zero2one_normally());
115
self.has_pushed_node = true;
116
self.has_strong_zero2one = true;
117
}
118
119
fn did_push_strong_zero2one_wrapper(&mut self) {
120
assert!(self.should_push_strong_zero2one());
121
assert!(!self.can_push_strong_zero2one_normally());
122
self.has_pushed_wrapper = true;
123
self.has_strong_zero2one = true;
124
}
125
}
126
127
struct CountState {
128
/// The reference count.
129
count: usize,
130
/// Whether the process that owns this node thinks that we hold a refcount on it. (Note that
131
/// even if count is greater than one, we only increment it once in the owning process.)
132
has_count: bool,
133
}
134
135
impl CountState {
136
fn new() -> Self {
137
Self {
138
count: 0,
139
has_count: false,
140
}
141
}
142
}
143
144
struct NodeInner {
145
/// Strong refcounts held on this node by `NodeRef` objects.
146
strong: CountState,
147
/// Weak refcounts held on this node by `NodeRef` objects.
148
weak: CountState,
149
delivery_state: DeliveryState,
150
/// The binder driver guarantees that oneway transactions sent to the same node are serialized,
151
/// that is, userspace will not be given the next one until it has finished processing the
152
/// previous oneway transaction. This is done to avoid the case where two oneway transactions
153
/// arrive in opposite order from the order in which they were sent. (E.g., they could be
154
/// delivered to two different threads, which could appear as-if they were sent in opposite
155
/// order.)
156
///
157
/// To fix that, we store pending oneway transactions in a separate list in the node, and don't
158
/// deliver the next oneway transaction until userspace signals that it has finished processing
159
/// the previous oneway transaction by calling the `BC_FREE_BUFFER` ioctl.
160
oneway_todo: List<DTRWrap<Transaction>>,
161
/// Keeps track of whether this node has a pending oneway transaction.
162
///
163
/// When this is true, incoming oneway transactions are stored in `oneway_todo`, instead of
164
/// being delivered directly to the process.
165
has_oneway_transaction: bool,
166
/// List of processes to deliver a notification to when this node is destroyed (usually due to
167
/// the process dying).
168
death_list: List<DTRWrap<NodeDeath>, 1>,
169
/// List of processes to deliver freeze notifications to.
170
freeze_list: KVVec<Arc<Process>>,
171
/// The number of active BR_INCREFS or BR_ACQUIRE operations. (should be maximum two)
172
///
173
/// If this is non-zero, then we postpone any BR_RELEASE or BR_DECREFS notifications until the
174
/// active operations have ended. This avoids the situation an increment and decrement get
175
/// reordered from userspace's perspective.
176
active_inc_refs: u8,
177
/// List of `NodeRefInfo` objects that reference this node.
178
refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
179
}
180
181
#[pin_data]
182
pub(crate) struct Node {
183
pub(crate) debug_id: usize,
184
ptr: u64,
185
pub(crate) cookie: u64,
186
pub(crate) flags: u32,
187
pub(crate) owner: Arc<Process>,
188
inner: LockedBy<NodeInner, ProcessInner>,
189
#[pin]
190
links_track: AtomicTracker,
191
}
192
193
kernel::list::impl_list_arc_safe! {
194
impl ListArcSafe<0> for Node {
195
tracked_by links_track: AtomicTracker;
196
}
197
}
198
199
// Make `oneway_todo` work.
200
kernel::list::impl_list_item! {
201
impl ListItem<0> for DTRWrap<Transaction> {
202
using ListLinks { self.links.inner };
203
}
204
}
205
206
impl Node {
207
pub(crate) fn new(
208
ptr: u64,
209
cookie: u64,
210
flags: u32,
211
owner: Arc<Process>,
212
) -> impl PinInit<Self> {
213
pin_init!(Self {
214
inner: LockedBy::new(
215
&owner.inner,
216
NodeInner {
217
strong: CountState::new(),
218
weak: CountState::new(),
219
delivery_state: DeliveryState {
220
has_pushed_node: false,
221
has_pushed_wrapper: false,
222
has_weak_zero2one: false,
223
has_strong_zero2one: false,
224
},
225
death_list: List::new(),
226
oneway_todo: List::new(),
227
freeze_list: KVVec::new(),
228
has_oneway_transaction: false,
229
active_inc_refs: 0,
230
refs: List::new(),
231
},
232
),
233
debug_id: super::next_debug_id(),
234
ptr,
235
cookie,
236
flags,
237
owner,
238
links_track <- AtomicTracker::new(),
239
})
240
}
241
242
pub(crate) fn has_oneway_transaction(&self, owner_inner: &mut ProcessInner) -> bool {
243
let inner = self.inner.access_mut(owner_inner);
244
inner.has_oneway_transaction
245
}
246
247
#[inline(never)]
248
pub(crate) fn full_debug_print(
249
&self,
250
m: &SeqFile,
251
owner_inner: &mut ProcessInner,
252
) -> Result<()> {
253
let inner = self.inner.access_mut(owner_inner);
254
seq_print!(
255
m,
256
" node {}: u{:016x} c{:016x} hs {} hw {} cs {} cw {}",
257
self.debug_id,
258
self.ptr,
259
self.cookie,
260
inner.strong.has_count,
261
inner.weak.has_count,
262
inner.strong.count,
263
inner.weak.count,
264
);
265
if !inner.refs.is_empty() {
266
seq_print!(m, " proc");
267
for node_ref in &inner.refs {
268
seq_print!(m, " {}", node_ref.process.task.pid());
269
}
270
}
271
seq_print!(m, "\n");
272
for t in &inner.oneway_todo {
273
t.debug_print_inner(m, " pending async transaction ");
274
}
275
Ok(())
276
}
277
278
/// Insert the `NodeRef` into this `refs` list.
279
///
280
/// # Safety
281
///
282
/// It must be the case that `info.node_ref.node` is this node.
283
pub(crate) unsafe fn insert_node_info(
284
&self,
285
info: ListArc<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
286
) {
287
self.inner
288
.access_mut(&mut self.owner.inner.lock())
289
.refs
290
.push_front(info);
291
}
292
293
/// Insert the `NodeRef` into this `refs` list.
294
///
295
/// # Safety
296
///
297
/// It must be the case that `info.node_ref.node` is this node.
298
pub(crate) unsafe fn remove_node_info(
299
&self,
300
info: &NodeRefInfo,
301
) -> Option<ListArc<NodeRefInfo, { NodeRefInfo::LIST_NODE }>> {
302
// SAFETY: We always insert `NodeRefInfo` objects into the `refs` list of the node that it
303
// references in `info.node_ref.node`. That is this node, so `info` cannot possibly be in
304
// the `refs` list of another node.
305
unsafe {
306
self.inner
307
.access_mut(&mut self.owner.inner.lock())
308
.refs
309
.remove(info)
310
}
311
}
312
313
/// An id that is unique across all binder nodes on the system. Used as the key in the
314
/// `by_node` map.
315
pub(crate) fn global_id(&self) -> usize {
316
self as *const Node as usize
317
}
318
319
pub(crate) fn get_id(&self) -> (u64, u64) {
320
(self.ptr, self.cookie)
321
}
322
323
pub(crate) fn add_death(
324
&self,
325
death: ListArc<DTRWrap<NodeDeath>, 1>,
326
guard: &mut Guard<'_, ProcessInner, SpinLockBackend>,
327
) {
328
self.inner.access_mut(guard).death_list.push_back(death);
329
}
330
331
pub(crate) fn inc_ref_done_locked(
332
self: &DArc<Node>,
333
_strong: bool,
334
owner_inner: &mut ProcessInner,
335
) -> Option<DLArc<Node>> {
336
let inner = self.inner.access_mut(owner_inner);
337
if inner.active_inc_refs == 0 {
338
pr_err!("inc_ref_done called when no active inc_refs");
339
return None;
340
}
341
342
inner.active_inc_refs -= 1;
343
if inner.active_inc_refs == 0 {
344
// Having active inc_refs can inhibit dropping of ref-counts. Calculate whether we
345
// would send a refcount decrement, and if so, tell the caller to schedule us.
346
let strong = inner.strong.count > 0;
347
let has_strong = inner.strong.has_count;
348
let weak = strong || inner.weak.count > 0;
349
let has_weak = inner.weak.has_count;
350
351
let should_drop_weak = !weak && has_weak;
352
let should_drop_strong = !strong && has_strong;
353
354
// If we want to drop the ref-count again, tell the caller to schedule a work node for
355
// that.
356
let need_push = should_drop_weak || should_drop_strong;
357
358
if need_push && inner.delivery_state.should_normal_push() {
359
let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap();
360
inner.delivery_state.did_normal_push();
361
Some(list_arc)
362
} else {
363
None
364
}
365
} else {
366
None
367
}
368
}
369
370
pub(crate) fn update_refcount_locked(
371
self: &DArc<Node>,
372
inc: bool,
373
strong: bool,
374
count: usize,
375
owner_inner: &mut ProcessInner,
376
) -> Option<DLArc<Node>> {
377
let is_dead = owner_inner.is_dead;
378
let inner = self.inner.access_mut(owner_inner);
379
380
// Get a reference to the state we'll update.
381
let state = if strong {
382
&mut inner.strong
383
} else {
384
&mut inner.weak
385
};
386
387
// Update the count and determine whether we need to push work.
388
let need_push = if inc {
389
state.count += count;
390
// TODO: This method shouldn't be used for zero-to-one increments.
391
!is_dead && !state.has_count
392
} else {
393
if state.count < count {
394
pr_err!("Failure: refcount underflow!");
395
return None;
396
}
397
state.count -= count;
398
!is_dead && state.count == 0 && state.has_count
399
};
400
401
if need_push && inner.delivery_state.should_normal_push() {
402
let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap();
403
inner.delivery_state.did_normal_push();
404
Some(list_arc)
405
} else {
406
None
407
}
408
}
409
410
pub(crate) fn incr_refcount_allow_zero2one(
411
self: &DArc<Self>,
412
strong: bool,
413
owner_inner: &mut ProcessInner,
414
) -> Result<Option<DLArc<Node>>, CouldNotDeliverCriticalIncrement> {
415
let is_dead = owner_inner.is_dead;
416
let inner = self.inner.access_mut(owner_inner);
417
418
// Get a reference to the state we'll update.
419
let state = if strong {
420
&mut inner.strong
421
} else {
422
&mut inner.weak
423
};
424
425
// Update the count and determine whether we need to push work.
426
state.count += 1;
427
if is_dead || state.has_count {
428
return Ok(None);
429
}
430
431
// Userspace needs to be notified of this.
432
if !strong && inner.delivery_state.should_push_weak_zero2one() {
433
assert!(inner.delivery_state.can_push_weak_zero2one_normally());
434
let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap();
435
inner.delivery_state.did_push_weak_zero2one();
436
Ok(Some(list_arc))
437
} else if strong && inner.delivery_state.should_push_strong_zero2one() {
438
if inner.delivery_state.can_push_strong_zero2one_normally() {
439
let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap();
440
inner.delivery_state.did_push_strong_zero2one();
441
Ok(Some(list_arc))
442
} else {
443
state.count -= 1;
444
Err(CouldNotDeliverCriticalIncrement)
445
}
446
} else {
447
// Work is already pushed, and we don't need to push again.
448
Ok(None)
449
}
450
}
451
452
pub(crate) fn incr_refcount_allow_zero2one_with_wrapper(
453
self: &DArc<Self>,
454
strong: bool,
455
wrapper: CritIncrWrapper,
456
owner_inner: &mut ProcessInner,
457
) -> Option<DLArc<dyn DeliverToRead>> {
458
match self.incr_refcount_allow_zero2one(strong, owner_inner) {
459
Ok(Some(node)) => Some(node as _),
460
Ok(None) => None,
461
Err(CouldNotDeliverCriticalIncrement) => {
462
assert!(strong);
463
let inner = self.inner.access_mut(owner_inner);
464
inner.strong.count += 1;
465
inner.delivery_state.did_push_strong_zero2one_wrapper();
466
Some(wrapper.init(self.clone()))
467
}
468
}
469
}
470
471
pub(crate) fn update_refcount(self: &DArc<Self>, inc: bool, count: usize, strong: bool) {
472
self.owner
473
.inner
474
.lock()
475
.update_node_refcount(self, inc, strong, count, None);
476
}
477
478
pub(crate) fn populate_counts(
479
&self,
480
out: &mut BinderNodeInfoForRef,
481
guard: &Guard<'_, ProcessInner, SpinLockBackend>,
482
) {
483
let inner = self.inner.access(guard);
484
out.strong_count = inner.strong.count as _;
485
out.weak_count = inner.weak.count as _;
486
}
487
488
pub(crate) fn populate_debug_info(
489
&self,
490
out: &mut BinderNodeDebugInfo,
491
guard: &Guard<'_, ProcessInner, SpinLockBackend>,
492
) {
493
out.ptr = self.ptr as _;
494
out.cookie = self.cookie as _;
495
let inner = self.inner.access(guard);
496
if inner.strong.has_count {
497
out.has_strong_ref = 1;
498
}
499
if inner.weak.has_count {
500
out.has_weak_ref = 1;
501
}
502
}
503
504
pub(crate) fn force_has_count(&self, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>) {
505
let inner = self.inner.access_mut(guard);
506
inner.strong.has_count = true;
507
inner.weak.has_count = true;
508
}
509
510
fn write(&self, writer: &mut BinderReturnWriter<'_>, code: u32) -> Result {
511
writer.write_code(code)?;
512
writer.write_payload(&self.ptr)?;
513
writer.write_payload(&self.cookie)?;
514
Ok(())
515
}
516
517
pub(crate) fn submit_oneway(
518
&self,
519
transaction: DLArc<Transaction>,
520
guard: &mut Guard<'_, ProcessInner, SpinLockBackend>,
521
) -> Result<(), (BinderError, DLArc<dyn DeliverToRead>)> {
522
if guard.is_dead {
523
return Err((BinderError::new_dead(), transaction));
524
}
525
526
let inner = self.inner.access_mut(guard);
527
if inner.has_oneway_transaction {
528
inner.oneway_todo.push_back(transaction);
529
} else {
530
inner.has_oneway_transaction = true;
531
guard.push_work(transaction)?;
532
}
533
Ok(())
534
}
535
536
pub(crate) fn release(&self) {
537
let mut guard = self.owner.inner.lock();
538
while let Some(work) = self.inner.access_mut(&mut guard).oneway_todo.pop_front() {
539
drop(guard);
540
work.into_arc().cancel();
541
guard = self.owner.inner.lock();
542
}
543
544
let death_list = core::mem::take(&mut self.inner.access_mut(&mut guard).death_list);
545
drop(guard);
546
for death in death_list {
547
death.into_arc().set_dead();
548
}
549
}
550
551
pub(crate) fn pending_oneway_finished(&self) {
552
let mut guard = self.owner.inner.lock();
553
if guard.is_dead {
554
// Cleanup will happen in `Process::deferred_release`.
555
return;
556
}
557
558
let inner = self.inner.access_mut(&mut guard);
559
560
let transaction = inner.oneway_todo.pop_front();
561
inner.has_oneway_transaction = transaction.is_some();
562
if let Some(transaction) = transaction {
563
match guard.push_work(transaction) {
564
Ok(()) => {}
565
Err((_err, work)) => {
566
// Process is dead.
567
// This shouldn't happen due to the `is_dead` check, but if it does, just drop
568
// the transaction and return.
569
drop(guard);
570
drop(work);
571
}
572
}
573
}
574
}
575
576
/// Finds an outdated transaction that the given transaction can replace.
577
///
578
/// If one is found, it is removed from the list and returned.
579
pub(crate) fn take_outdated_transaction(
580
&self,
581
new: &Transaction,
582
guard: &mut Guard<'_, ProcessInner, SpinLockBackend>,
583
) -> Option<DLArc<Transaction>> {
584
let inner = self.inner.access_mut(guard);
585
let mut cursor = inner.oneway_todo.cursor_front();
586
while let Some(next) = cursor.peek_next() {
587
if new.can_replace(&next) {
588
return Some(next.remove());
589
}
590
cursor.move_next();
591
}
592
None
593
}
594
595
/// This is split into a separate function since it's called by both `Node::do_work` and
596
/// `NodeWrapper::do_work`.
597
fn do_work_locked(
598
&self,
599
writer: &mut BinderReturnWriter<'_>,
600
mut guard: Guard<'_, ProcessInner, SpinLockBackend>,
601
) -> Result<bool> {
602
let inner = self.inner.access_mut(&mut guard);
603
let strong = inner.strong.count > 0;
604
let has_strong = inner.strong.has_count;
605
let weak = strong || inner.weak.count > 0;
606
let has_weak = inner.weak.has_count;
607
608
if weak && !has_weak {
609
inner.weak.has_count = true;
610
inner.active_inc_refs += 1;
611
}
612
613
if strong && !has_strong {
614
inner.strong.has_count = true;
615
inner.active_inc_refs += 1;
616
}
617
618
let no_active_inc_refs = inner.active_inc_refs == 0;
619
let should_drop_weak = no_active_inc_refs && (!weak && has_weak);
620
let should_drop_strong = no_active_inc_refs && (!strong && has_strong);
621
if should_drop_weak {
622
inner.weak.has_count = false;
623
}
624
if should_drop_strong {
625
inner.strong.has_count = false;
626
}
627
if no_active_inc_refs && !weak {
628
// Remove the node if there are no references to it.
629
guard.remove_node(self.ptr);
630
}
631
drop(guard);
632
633
if weak && !has_weak {
634
self.write(writer, BR_INCREFS)?;
635
}
636
if strong && !has_strong {
637
self.write(writer, BR_ACQUIRE)?;
638
}
639
if should_drop_strong {
640
self.write(writer, BR_RELEASE)?;
641
}
642
if should_drop_weak {
643
self.write(writer, BR_DECREFS)?;
644
}
645
646
Ok(true)
647
}
648
649
pub(crate) fn add_freeze_listener(
650
&self,
651
process: &Arc<Process>,
652
flags: kernel::alloc::Flags,
653
) -> Result {
654
let mut vec_alloc = KVVec::<Arc<Process>>::new();
655
loop {
656
let mut guard = self.owner.inner.lock();
657
// Do not check for `guard.dead`. The `dead` flag that matters here is the owner of the
658
// listener, no the target.
659
let inner = self.inner.access_mut(&mut guard);
660
let len = inner.freeze_list.len();
661
if len >= inner.freeze_list.capacity() {
662
if len >= vec_alloc.capacity() {
663
drop(guard);
664
vec_alloc = KVVec::with_capacity((1 + len).next_power_of_two(), flags)?;
665
continue;
666
}
667
mem::swap(&mut inner.freeze_list, &mut vec_alloc);
668
for elem in vec_alloc.drain_all() {
669
inner.freeze_list.push_within_capacity(elem)?;
670
}
671
}
672
inner.freeze_list.push_within_capacity(process.clone())?;
673
return Ok(());
674
}
675
}
676
677
pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
678
let _unused_capacity;
679
let mut guard = self.owner.inner.lock();
680
let inner = self.inner.access_mut(&mut guard);
681
let len = inner.freeze_list.len();
682
inner.freeze_list.retain(|proc| !Arc::ptr_eq(proc, p));
683
if len == inner.freeze_list.len() {
684
pr_warn!(
685
"Could not remove freeze listener for {}\n",
686
p.pid_in_current_ns()
687
);
688
}
689
if inner.freeze_list.is_empty() {
690
_unused_capacity = mem::replace(&mut inner.freeze_list, KVVec::new());
691
}
692
}
693
694
pub(crate) fn freeze_list<'a>(&'a self, guard: &'a ProcessInner) -> &'a [Arc<Process>] {
695
&self.inner.access(guard).freeze_list
696
}
697
}
698
699
impl DeliverToRead for Node {
700
fn do_work(
701
self: DArc<Self>,
702
_thread: &Thread,
703
writer: &mut BinderReturnWriter<'_>,
704
) -> Result<bool> {
705
let mut owner_inner = self.owner.inner.lock();
706
let inner = self.inner.access_mut(&mut owner_inner);
707
708
assert!(inner.delivery_state.has_pushed_node);
709
if inner.delivery_state.has_pushed_wrapper {
710
// If the wrapper is scheduled, then we are either a normal push or weak zero2one
711
// increment, and the wrapper is a strong zero2one increment, so the wrapper always
712
// takes precedence over us.
713
assert!(inner.delivery_state.has_strong_zero2one);
714
inner.delivery_state.has_pushed_node = false;
715
inner.delivery_state.has_weak_zero2one = false;
716
return Ok(true);
717
}
718
719
inner.delivery_state.has_pushed_node = false;
720
inner.delivery_state.has_weak_zero2one = false;
721
inner.delivery_state.has_strong_zero2one = false;
722
723
self.do_work_locked(writer, owner_inner)
724
}
725
726
fn cancel(self: DArc<Self>) {}
727
728
fn should_sync_wakeup(&self) -> bool {
729
false
730
}
731
732
#[inline(never)]
733
fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
734
seq_print!(
735
m,
736
"{}node work {}: u{:016x} c{:016x}\n",
737
prefix,
738
self.debug_id,
739
self.ptr,
740
self.cookie,
741
);
742
Ok(())
743
}
744
}
745
746
/// Represents something that holds one or more ref-counts to a `Node`.
747
///
748
/// Whenever process A holds a refcount to a node owned by a different process B, then process A
749
/// will store a `NodeRef` that refers to the `Node` in process B. When process A releases the
750
/// refcount, we destroy the NodeRef, which decrements the ref-count in process A.
751
///
752
/// This type is also used for some other cases. For example, a transaction allocation holds a
753
/// refcount on the target node, and this is implemented by storing a `NodeRef` in the allocation
754
/// so that the destructor of the allocation will drop a refcount of the `Node`.
755
pub(crate) struct NodeRef {
756
pub(crate) node: DArc<Node>,
757
/// How many times does this NodeRef hold a refcount on the Node?
758
strong_node_count: usize,
759
weak_node_count: usize,
760
/// How many times does userspace hold a refcount on this NodeRef?
761
strong_count: usize,
762
weak_count: usize,
763
}
764
765
impl NodeRef {
766
pub(crate) fn new(node: DArc<Node>, strong_count: usize, weak_count: usize) -> Self {
767
Self {
768
node,
769
strong_node_count: strong_count,
770
weak_node_count: weak_count,
771
strong_count,
772
weak_count,
773
}
774
}
775
776
pub(crate) fn absorb(&mut self, mut other: Self) {
777
assert!(
778
Arc::ptr_eq(&self.node, &other.node),
779
"absorb called with differing nodes"
780
);
781
self.strong_node_count += other.strong_node_count;
782
self.weak_node_count += other.weak_node_count;
783
self.strong_count += other.strong_count;
784
self.weak_count += other.weak_count;
785
other.strong_count = 0;
786
other.weak_count = 0;
787
other.strong_node_count = 0;
788
other.weak_node_count = 0;
789
790
if self.strong_node_count >= 2 || self.weak_node_count >= 2 {
791
let mut guard = self.node.owner.inner.lock();
792
let inner = self.node.inner.access_mut(&mut guard);
793
794
if self.strong_node_count >= 2 {
795
inner.strong.count -= self.strong_node_count - 1;
796
self.strong_node_count = 1;
797
assert_ne!(inner.strong.count, 0);
798
}
799
if self.weak_node_count >= 2 {
800
inner.weak.count -= self.weak_node_count - 1;
801
self.weak_node_count = 1;
802
assert_ne!(inner.weak.count, 0);
803
}
804
}
805
}
806
807
pub(crate) fn get_count(&self) -> (usize, usize) {
808
(self.strong_count, self.weak_count)
809
}
810
811
pub(crate) fn clone(&self, strong: bool) -> Result<NodeRef> {
812
if strong && self.strong_count == 0 {
813
return Err(EINVAL);
814
}
815
Ok(self
816
.node
817
.owner
818
.inner
819
.lock()
820
.new_node_ref(self.node.clone(), strong, None))
821
}
822
823
/// Updates (increments or decrements) the number of references held against the node. If the
824
/// count being updated transitions from 0 to 1 or from 1 to 0, the node is notified by having
825
/// its `update_refcount` function called.
826
///
827
/// Returns whether `self` should be removed (when both counts are zero).
828
pub(crate) fn update(&mut self, inc: bool, strong: bool) -> bool {
829
if strong && self.strong_count == 0 {
830
return false;
831
}
832
let (count, node_count, other_count) = if strong {
833
(
834
&mut self.strong_count,
835
&mut self.strong_node_count,
836
self.weak_count,
837
)
838
} else {
839
(
840
&mut self.weak_count,
841
&mut self.weak_node_count,
842
self.strong_count,
843
)
844
};
845
if inc {
846
if *count == 0 {
847
*node_count = 1;
848
self.node.update_refcount(true, 1, strong);
849
}
850
*count += 1;
851
} else {
852
if *count == 0 {
853
pr_warn!(
854
"pid {} performed invalid decrement on ref\n",
855
kernel::current!().pid()
856
);
857
return false;
858
}
859
*count -= 1;
860
if *count == 0 {
861
self.node.update_refcount(false, *node_count, strong);
862
*node_count = 0;
863
return other_count == 0;
864
}
865
}
866
false
867
}
868
}
869
870
impl Drop for NodeRef {
871
// This destructor is called conditionally from `Allocation::drop`. That branch is often
872
// mispredicted. Inlining this method call reduces the cost of those branch mispredictions.
873
#[inline(always)]
874
fn drop(&mut self) {
875
if self.strong_node_count > 0 {
876
self.node
877
.update_refcount(false, self.strong_node_count, true);
878
}
879
if self.weak_node_count > 0 {
880
self.node
881
.update_refcount(false, self.weak_node_count, false);
882
}
883
}
884
}
885
886
struct NodeDeathInner {
887
dead: bool,
888
cleared: bool,
889
notification_done: bool,
890
/// Indicates whether the normal flow was interrupted by removing the handle. In this case, we
891
/// need behave as if the death notification didn't exist (i.e., we don't deliver anything to
892
/// the user.
893
aborted: bool,
894
}
895
896
/// Used to deliver notifications when a process dies.
897
///
898
/// A process can request to be notified when a process dies using `BC_REQUEST_DEATH_NOTIFICATION`.
899
/// This will make the driver send a `BR_DEAD_BINDER` to userspace when the process dies (or
900
/// immediately if it is already dead). Userspace is supposed to respond with `BC_DEAD_BINDER_DONE`
901
/// once it has processed the notification.
902
///
903
/// Userspace can unregister from death notifications using the `BC_CLEAR_DEATH_NOTIFICATION`
904
/// command. In this case, the kernel will respond with `BR_CLEAR_DEATH_NOTIFICATION_DONE` once the
905
/// notification has been removed. Note that if the remote process dies before the kernel has
906
/// responded with `BR_CLEAR_DEATH_NOTIFICATION_DONE`, then the kernel will still send a
907
/// `BR_DEAD_BINDER`, which userspace must be able to process. In this case, the kernel will wait
908
/// for the `BC_DEAD_BINDER_DONE` command before it sends `BR_CLEAR_DEATH_NOTIFICATION_DONE`.
909
///
910
/// Note that even if the kernel sends a `BR_DEAD_BINDER`, this does not remove the death
911
/// notification. Userspace must still remove it manually using `BC_CLEAR_DEATH_NOTIFICATION`.
912
///
913
/// If a process uses `BC_RELEASE` to destroy its last refcount on a node that has an active death
914
/// registration, then the death registration is immediately deleted (we implement this using the
915
/// `aborted` field). However, userspace is not supposed to delete a `NodeRef` without first
916
/// deregistering death notifications, so this codepath is not executed under normal circumstances.
917
#[pin_data]
918
pub(crate) struct NodeDeath {
919
node: DArc<Node>,
920
process: Arc<Process>,
921
pub(crate) cookie: u64,
922
#[pin]
923
links_track: AtomicTracker<0>,
924
/// Used by the owner `Node` to store a list of registered death notifications.
925
///
926
/// # Invariants
927
///
928
/// Only ever used with the `death_list` list of `self.node`.
929
#[pin]
930
death_links: ListLinks<1>,
931
/// Used by the process to keep track of the death notifications for which we have sent a
932
/// `BR_DEAD_BINDER` but not yet received a `BC_DEAD_BINDER_DONE`.
933
///
934
/// # Invariants
935
///
936
/// Only ever used with the `delivered_deaths` list of `self.process`.
937
#[pin]
938
delivered_links: ListLinks<2>,
939
#[pin]
940
delivered_links_track: AtomicTracker<2>,
941
#[pin]
942
inner: SpinLock<NodeDeathInner>,
943
}
944
945
impl NodeDeath {
946
/// Constructs a new node death notification object.
947
pub(crate) fn new(
948
node: DArc<Node>,
949
process: Arc<Process>,
950
cookie: u64,
951
) -> impl PinInit<DTRWrap<Self>> {
952
DTRWrap::new(pin_init!(
953
Self {
954
node,
955
process,
956
cookie,
957
links_track <- AtomicTracker::new(),
958
death_links <- ListLinks::new(),
959
delivered_links <- ListLinks::new(),
960
delivered_links_track <- AtomicTracker::new(),
961
inner <- kernel::new_spinlock!(NodeDeathInner {
962
dead: false,
963
cleared: false,
964
notification_done: false,
965
aborted: false,
966
}, "NodeDeath::inner"),
967
}
968
))
969
}
970
971
/// Sets the cleared flag to `true`.
972
///
973
/// It removes `self` from the node's death notification list if needed.
974
///
975
/// Returns whether it needs to be queued.
976
pub(crate) fn set_cleared(self: &DArc<Self>, abort: bool) -> bool {
977
let (needs_removal, needs_queueing) = {
978
// Update state and determine if we need to queue a work item. We only need to do it
979
// when the node is not dead or if the user already completed the death notification.
980
let mut inner = self.inner.lock();
981
if abort {
982
inner.aborted = true;
983
}
984
if inner.cleared {
985
// Already cleared.
986
return false;
987
}
988
inner.cleared = true;
989
(!inner.dead, !inner.dead || inner.notification_done)
990
};
991
992
// Remove death notification from node.
993
if needs_removal {
994
let mut owner_inner = self.node.owner.inner.lock();
995
let node_inner = self.node.inner.access_mut(&mut owner_inner);
996
// SAFETY: A `NodeDeath` is never inserted into the death list of any node other than
997
// its owner, so it is either in this death list or in no death list.
998
unsafe { node_inner.death_list.remove(self) };
999
}
1000
needs_queueing
1001
}
1002
1003
/// Sets the 'notification done' flag to `true`.
1004
pub(crate) fn set_notification_done(self: DArc<Self>, thread: &Thread) {
1005
let needs_queueing = {
1006
let mut inner = self.inner.lock();
1007
inner.notification_done = true;
1008
inner.cleared
1009
};
1010
if needs_queueing {
1011
if let Some(death) = ListArc::try_from_arc_or_drop(self) {
1012
let _ = thread.push_work_if_looper(death);
1013
}
1014
}
1015
}
1016
1017
/// Sets the 'dead' flag to `true` and queues work item if needed.
1018
pub(crate) fn set_dead(self: DArc<Self>) {
1019
let needs_queueing = {
1020
let mut inner = self.inner.lock();
1021
if inner.cleared {
1022
false
1023
} else {
1024
inner.dead = true;
1025
true
1026
}
1027
};
1028
if needs_queueing {
1029
// Push the death notification to the target process. There is nothing else to do if
1030
// it's already dead.
1031
if let Some(death) = ListArc::try_from_arc_or_drop(self) {
1032
let process = death.process.clone();
1033
let _ = process.push_work(death);
1034
}
1035
}
1036
}
1037
}
1038
1039
kernel::list::impl_list_arc_safe! {
1040
impl ListArcSafe<0> for NodeDeath {
1041
tracked_by links_track: AtomicTracker;
1042
}
1043
}
1044
1045
kernel::list::impl_list_arc_safe! {
1046
impl ListArcSafe<1> for DTRWrap<NodeDeath> { untracked; }
1047
}
1048
kernel::list::impl_list_item! {
1049
impl ListItem<1> for DTRWrap<NodeDeath> {
1050
using ListLinks { self.wrapped.death_links };
1051
}
1052
}
1053
1054
kernel::list::impl_list_arc_safe! {
1055
impl ListArcSafe<2> for DTRWrap<NodeDeath> {
1056
tracked_by wrapped: NodeDeath;
1057
}
1058
}
1059
kernel::list::impl_list_arc_safe! {
1060
impl ListArcSafe<2> for NodeDeath {
1061
tracked_by delivered_links_track: AtomicTracker<2>;
1062
}
1063
}
1064
kernel::list::impl_list_item! {
1065
impl ListItem<2> for DTRWrap<NodeDeath> {
1066
using ListLinks { self.wrapped.delivered_links };
1067
}
1068
}
1069
1070
impl DeliverToRead for NodeDeath {
1071
fn do_work(
1072
self: DArc<Self>,
1073
_thread: &Thread,
1074
writer: &mut BinderReturnWriter<'_>,
1075
) -> Result<bool> {
1076
let done = {
1077
let inner = self.inner.lock();
1078
if inner.aborted {
1079
return Ok(true);
1080
}
1081
inner.cleared && (!inner.dead || inner.notification_done)
1082
};
1083
1084
let cookie = self.cookie;
1085
let cmd = if done {
1086
BR_CLEAR_DEATH_NOTIFICATION_DONE
1087
} else {
1088
let process = self.process.clone();
1089
let mut process_inner = process.inner.lock();
1090
let inner = self.inner.lock();
1091
if inner.aborted {
1092
return Ok(true);
1093
}
1094
// We're still holding the inner lock, so it cannot be aborted while we insert it into
1095
// the delivered list.
1096
process_inner.death_delivered(self.clone());
1097
BR_DEAD_BINDER
1098
};
1099
1100
writer.write_code(cmd)?;
1101
writer.write_payload(&cookie)?;
1102
// DEAD_BINDER notifications can cause transactions, so stop processing work items when we
1103
// get to a death notification.
1104
Ok(cmd != BR_DEAD_BINDER)
1105
}
1106
1107
fn cancel(self: DArc<Self>) {}
1108
1109
fn should_sync_wakeup(&self) -> bool {
1110
false
1111
}
1112
1113
#[inline(never)]
1114
fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
1115
let inner = self.inner.lock();
1116
1117
let dead_binder = inner.dead && !inner.notification_done;
1118
1119
if dead_binder {
1120
if inner.cleared {
1121
seq_print!(m, "{}has cleared dead binder\n", prefix);
1122
} else {
1123
seq_print!(m, "{}has dead binder\n", prefix);
1124
}
1125
} else {
1126
seq_print!(m, "{}has cleared death notification\n", prefix);
1127
}
1128
1129
Ok(())
1130
}
1131
}
1132
1133