On 8/7/25 14:29, Manos Pitsidianakis wrote:

+//! Bindings for `rcu_read_lock` and `rcu_read_unlock`.
+//! More details about RCU in QEMU, please refer docs/devel/rcu.rst.
+

How about a RAII guard type? e.g. RCUGuard and runs `rcu_read_unlock` on Drop.

Clippy says Rcu not RCU.  :)

You're right, not just because it's nice but also because it bounds the dereference of the FlatView. Something like this build on top of the guard object:

pub struct RcuCell<T> {
    data: AtomicPtr<T>
}

impl<T> RcuCell {
    pub fn raw_get(&self) -> *mut T {
        self.data.load(Ordering::Acquire)
    }

    pub fn get<'g>(&self, _: &'g RcuGuard) -> Option<&'g T> {
        unsafe {
            self.raw_get().as_ref()
        }
    }
}

Using this is a bit ugly, because you need transmute, but it's isolated:

impl AddressSpace {
   pub fn get_flatview(&self, rcu: &'g Guard) -> &'g FlatView {
       let flatp = unsafe {
           std::mem::transmute::<&*mut FlatView, &RcuCell<FlatView>>(
               &self.0.as_ptr().current_map)
       };
       flatp.get(rcu)
   }
}

impl GuestAddressSpace for AddressSpace {
    fn memory(&self) -> Self::T {
        let rcu = RcuGuard::guard();
        FlatViewRefGuard::new(self.get_flatview(rcu))
    }
}

Destructors are not guaranteed to run or run only once, but the former
should happen when things go wrong e.g. crashes/aborts. You can add a
flag in the RCUGuard to make sure Drop runs unlock only once (since it
takes &mut and not ownership)

Yeah I think many things would go wrong if Arc could run its drop implementation more than once.

Paolo


Reply via email to