drivers/android/binder/freeze.rs

Source file repositories/reference/linux-study-clean/drivers/android/binder/freeze.rs

File Facts

System
Linux kernel
Corpus path
drivers/android/binder/freeze.rs
Extension
.rs
Size
14742 bytes
Lines
399
Domain
Driver Families
Bucket
drivers/android
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

fn cancel(self: DArc<Self>) {}

    fn should_sync_wakeup(&self) -> bool {
        false
    }

    #[inline(never)]
    fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
        seq_print!(m, "{}has frozen binder\n", prefix);
        Ok(())
    }
}

impl FreezeListener {
    pub(crate) fn on_process_exit(&self, proc: &Arc<Process>) {
        if !self.is_clearing {
            self.node.remove_freeze_listener(proc);
        }
    }
}

impl Process {
    pub(crate) fn request_freeze_notif(
        self: &Arc<Self>,
        reader: &mut UserSliceReader,
    ) -> Result<()> {
        let hc = reader.read::<BinderHandleCookie>()?;
        let handle = hc.handle;
        let cookie = FreezeCookie(hc.cookie);

        let msg = FreezeMessage::new(GFP_KERNEL)?;
        let alloc = RBTreeNodeReservation::new(GFP_KERNEL)?;

        let mut node_refs_guard = self.node_refs.lock();
        let node_refs = &mut *node_refs_guard;
        let Some(info) = node_refs.by_handle.get_mut(&handle) else {
            pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION invalid ref {}\n", handle);
            return Err(EINVAL);
        };
        if info.freeze().is_some() {
            pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION already set\n");
            return Err(EINVAL);
        }
        let node_ref = info.node_ref();
        let freeze_entry = node_refs.freeze_listeners.entry(cookie);

        if let rbtree::Entry::Occupied(ref dupe) = freeze_entry {
            if !dupe.get().allow_duplicate(&node_ref.node) {
                pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION duplicate cookie\n");
                return Err(EINVAL);
            }
        }

        // All failure paths must come before this call, and all modifications must come after this
        // call.
        node_ref.node.add_freeze_listener(self, GFP_KERNEL)?;

        match freeze_entry {
            rbtree::Entry::Vacant(entry) => {
                entry.insert(
                    FreezeListener {
                        cookie,
                        node: node_ref.node.clone(),
                        last_is_frozen: None,
                        is_pending: false,
                        is_clearing: false,
                        num_pending_duplicates: 0,
                        num_cleared_duplicates: 0,
                    },
                    alloc,
                );
            }
            rbtree::Entry::Occupied(mut dupe) => {
                let dupe = dupe.get_mut();
                if dupe.is_pending {
                    dupe.num_pending_duplicates += 1;
                } else {
                    dupe.num_cleared_duplicates += 1;
                }
                dupe.last_is_frozen = None;
                dupe.is_pending = false;
                dupe.is_clearing = false;
            }
        }

        *info.freeze() = Some(cookie);
        let msg = FreezeMessage::init(msg, cookie);
        drop(node_refs_guard);
        let _ = self.push_work(msg);
        Ok(())

Annotation

Implementation Notes