Is it possible to borrow something in delay?

⚓ rust    📅 2025-06-08    👤 surdeus    👁️ 3      

surdeus

I'm implementing wrapper for UEFI protocol which uses FFI heavily. but I have trouble implementing Drop in a way that doesn't massively disrupt other code base.
I have struct that represents a region of memory, PciMappedRegion.
The address number it stores is mapped that it's usable by PCI device.

/// Represents a region of memory mapped by PCI Root Bridge I/O protocol.
/// The region will be unmapped automatically when it is dropped.
///
/// # Lifetime
/// `'p` is the lifetime for Protocol.
/// `'r` is the lifetime for Mapped Region.
/// Protocol must outlive the mapped region
/// as unmap function can only be accessed through the protocol.
#[derive(Debug)]
pub struct PciMappedRegion<'p, 'r>
where
    'p: 'r,
{
    region: PciRegion,
    _lifetime_holder: &'r (),
    key: *const c_void,
    proto: &'p PciRootBridgeIoProtocol,
}

/// Represents a region of memory in PCI root bridge memory space.
/// CPU cannot use address in this struct to deference memory.
/// This is effectively the same as rust's slice type.
/// This type only exists to prevent users from accidentally dereferencing it.
#[derive(Debug, Copy, Clone)]
pub struct PciRegion {
    /// Starting address of the memory region
    pub device_address: u64,

    /// Byte length of the memory region.
    pub length: usize
}

Since I don't want the memory to be dropped before the PciRegion is removed, it has lifetime parameter 'r.
In order to free the mapped region, it needs call a method in a struct PciRootBridgeIoProtocol. so it also has lifetime parameter 'p.
Here, p must outlive r. I assumed that Protocol would live quite long.
The problem is, the mapped region holds immutable reference to the Protocol struct. But other parts of code needs to call methods in there as well. and some of those methods needs mutable reference to the protocol.
So it is not possible to use call those methods when the mapped region is alive.
and I can't make users work around this issue themselves because this is very critical to one use case:
One of methods of the PciRootBridgeIoProtocol is one that copies memory. it needs mutable reference to the protocol struct, and two regions of mapped memory region.
So it needs those mapped region alive, and it also needs mutable reference to the protocol which is just not possible.

Is it possible to borrow Protocol struct only when it's being dropped? The mapped region only needs it when it's being dropped, so I don't think holding its reference entire time is good idea.

2 posts - 1 participant

Read full topic

🏷️ rust_feed