rust/kernel/device/property.rs

Source file repositories/reference/linux-study-clean/rust/kernel/device/property.rs

File Facts

System
Linux kernel
Corpus path
rust/kernel/device/property.rs
Extension
.rs
Size
24248 bytes
Lines
634
Domain
Rust Kernel Layer
Bucket
Rust API Membrane
Inferred role
Rust Kernel Layer: implementation source
Status
source implementation candidate

Why This File Exists

Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.

Dependency Surface

Detected Declarations

Annotated Snippet

fn drop(&mut self) {
        if !self.0.fwnode.is_null() {
            // SAFETY:
            // - By the type invariants of `FwNodeReferenceArgs`, its field
            //   `fwnode` owns an increment of its refcount.
            // - That increment is relinquished. The underlying object won't be
            //   used anymore because we are dropping it.
            let _ = unsafe { FwNode::from_raw(self.0.fwnode) };
        }
    }
}

impl FwNodeReferenceArgs {
    /// Returns the slice of reference arguments.
    pub fn as_slice(&self) -> &[u64] {
        // SAFETY: As per the safety invariant of `FwNodeReferenceArgs`, `nargs`
        // is the minimum number of elements in `args` that is valid.
        unsafe { core::slice::from_raw_parts(self.0.args.as_ptr(), self.0.nargs as usize) }
    }

    /// Returns the number of reference arguments.
    pub fn len(&self) -> usize {
        self.0.nargs as usize
    }

    /// Returns `true` if there are no reference arguments.
    pub fn is_empty(&self) -> bool {
        self.0.nargs == 0
    }
}

impl fmt::Debug for FwNodeReferenceArgs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self.as_slice())
    }
}

// SAFETY: Instances of `FwNode` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for FwNode {
    fn inc_ref(&self) {
        // SAFETY: The existence of a shared reference guarantees that the
        // refcount is non-zero.
        unsafe { bindings::fwnode_handle_get(self.as_raw()) };
    }

    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
        // SAFETY: The safety requirements guarantee that the refcount is
        // non-zero.
        unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) }
    }
}

enum Node<'a> {
    Borrowed(&'a FwNode),
    Owned(ARef<FwNode>),
}

impl fmt::Display for FwNode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // The logic here is the same as the one in lib/vsprintf.c
        // (fwnode_full_name_string).

        // SAFETY: `self.as_raw()` is valid by its type invariant.
        let num_parents = unsafe { bindings::fwnode_count_parents(self.as_raw()) };

        for depth in (0..=num_parents).rev() {
            let fwnode = if depth == 0 {
                Node::Borrowed(self)
            } else {
                // SAFETY: `self.as_raw()` is valid.
                let ptr = unsafe { bindings::fwnode_get_nth_parent(self.as_raw(), depth) };
                // SAFETY:
                // - The depth passed to `fwnode_get_nth_parent` is
                //   within the valid range, so the returned pointer is
                //   not null.
                // - The reference count was incremented by
                //   `fwnode_get_nth_parent`.
                // - That increment is relinquished to
                //   `FwNode::from_raw`.
                Node::Owned(unsafe { FwNode::from_raw(ptr) })
            };
            // Take a reference to the owned or borrowed `FwNode`.
            let fwnode: &FwNode = match &fwnode {
                Node::Borrowed(f) => f,
                Node::Owned(f) => f,
            };

            // SAFETY: `fwnode` is valid by its type invariant.
            let prefix = unsafe { bindings::fwnode_get_name_prefix(fwnode.as_raw()) };
            if !prefix.is_null() {

Annotation

Implementation Notes