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