18e194c0eSPaolo Bonzini // SPDX-License-Identifier: MIT 28e194c0eSPaolo Bonzini // 38e194c0eSPaolo Bonzini // This file is based on library/core/src/cell.rs from 48e194c0eSPaolo Bonzini // Rust 1.82.0. 58e194c0eSPaolo Bonzini // 68e194c0eSPaolo Bonzini // Permission is hereby granted, free of charge, to any 78e194c0eSPaolo Bonzini // person obtaining a copy of this software and associated 88e194c0eSPaolo Bonzini // documentation files (the "Software"), to deal in the 98e194c0eSPaolo Bonzini // Software without restriction, including without 108e194c0eSPaolo Bonzini // limitation the rights to use, copy, modify, merge, 118e194c0eSPaolo Bonzini // publish, distribute, sublicense, and/or sell copies of 128e194c0eSPaolo Bonzini // the Software, and to permit persons to whom the Software 138e194c0eSPaolo Bonzini // is furnished to do so, subject to the following 148e194c0eSPaolo Bonzini // conditions: 158e194c0eSPaolo Bonzini // 168e194c0eSPaolo Bonzini // The above copyright notice and this permission notice 178e194c0eSPaolo Bonzini // shall be included in all copies or substantial portions 188e194c0eSPaolo Bonzini // of the Software. 198e194c0eSPaolo Bonzini // 208e194c0eSPaolo Bonzini // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 218e194c0eSPaolo Bonzini // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 228e194c0eSPaolo Bonzini // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 238e194c0eSPaolo Bonzini // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 248e194c0eSPaolo Bonzini // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 258e194c0eSPaolo Bonzini // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 268e194c0eSPaolo Bonzini // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 278e194c0eSPaolo Bonzini // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 288e194c0eSPaolo Bonzini // DEALINGS IN THE SOFTWARE. 298e194c0eSPaolo Bonzini 308e194c0eSPaolo Bonzini //! BQL-protected mutable containers. 318e194c0eSPaolo Bonzini //! 328e194c0eSPaolo Bonzini //! Rust memory safety is based on this rule: Given an object `T`, it is only 338e194c0eSPaolo Bonzini //! possible to have one of the following: 348e194c0eSPaolo Bonzini //! 358e194c0eSPaolo Bonzini //! - Having several immutable references (`&T`) to the object (also known as 368e194c0eSPaolo Bonzini //! **aliasing**). 378e194c0eSPaolo Bonzini //! - Having one mutable reference (`&mut T`) to the object (also known as 388e194c0eSPaolo Bonzini //! **mutability**). 398e194c0eSPaolo Bonzini //! 408e194c0eSPaolo Bonzini //! This is enforced by the Rust compiler. However, there are situations where 418e194c0eSPaolo Bonzini //! this rule is not flexible enough. Sometimes it is required to have multiple 428e194c0eSPaolo Bonzini //! references to an object and yet mutate it. In particular, QEMU objects 438e194c0eSPaolo Bonzini //! usually have their pointer shared with the "outside world very early in 448e194c0eSPaolo Bonzini //! their lifetime", for example when they create their 458e194c0eSPaolo Bonzini //! [`MemoryRegion`s](crate::bindings::MemoryRegion). Therefore, individual 468e194c0eSPaolo Bonzini //! parts of a device must be made mutable in a controlled manner through the 478e194c0eSPaolo Bonzini //! use of cell types. 488e194c0eSPaolo Bonzini //! 49*c596199fSPaolo Bonzini //! [`BqlCell<T>`] and [`BqlRefCell<T>`] allow doing this via the Big QEMU Lock. 50*c596199fSPaolo Bonzini //! While they are essentially the same single-threaded primitives that are 51*c596199fSPaolo Bonzini //! available in `std::cell`, the BQL allows them to be used from a 52*c596199fSPaolo Bonzini //! multi-threaded context and to share references across threads, while 53*c596199fSPaolo Bonzini //! maintaining Rust's safety guarantees. For this reason, unlike 54*c596199fSPaolo Bonzini //! their `std::cell` counterparts, `BqlCell` and `BqlRefCell` implement the 55*c596199fSPaolo Bonzini //! `Sync` trait. 568e194c0eSPaolo Bonzini //! 578e194c0eSPaolo Bonzini //! BQL checks are performed in debug builds but can be optimized away in 588e194c0eSPaolo Bonzini //! release builds, providing runtime safety during development with no overhead 598e194c0eSPaolo Bonzini //! in production. 608e194c0eSPaolo Bonzini //! 61*c596199fSPaolo Bonzini //! The two provide different ways of handling interior mutability. 62*c596199fSPaolo Bonzini //! `BqlRefCell` is best suited for data that is primarily accessed by the 63*c596199fSPaolo Bonzini //! device's own methods, where multiple reads and writes can be grouped within 64*c596199fSPaolo Bonzini //! a single borrow and a mutable reference can be passed around. Instead, 65*c596199fSPaolo Bonzini //! [`BqlCell`] is a better choice when sharing small pieces of data with 66*c596199fSPaolo Bonzini //! external code (especially C code), because it provides simple get/set 67*c596199fSPaolo Bonzini //! operations that can be used one at a time. 68*c596199fSPaolo Bonzini //! 69*c596199fSPaolo Bonzini //! Warning: While `BqlCell` and `BqlRefCell` are similar to their `std::cell` 70*c596199fSPaolo Bonzini //! counterparts, they are not interchangeable. Using `std::cell` types in 71*c596199fSPaolo Bonzini //! QEMU device implementations is usually incorrect and can lead to 72*c596199fSPaolo Bonzini //! thread-safety issues. 738e194c0eSPaolo Bonzini //! 748e194c0eSPaolo Bonzini //! ## `BqlCell<T>` 758e194c0eSPaolo Bonzini //! 768e194c0eSPaolo Bonzini //! [`BqlCell<T>`] implements interior mutability by moving values in and out of 778e194c0eSPaolo Bonzini //! the cell. That is, an `&mut T` to the inner value can never be obtained as 788e194c0eSPaolo Bonzini //! long as the cell is shared. The value itself cannot be directly obtained 798e194c0eSPaolo Bonzini //! without copying it, cloning it, or replacing it with something else. This 808e194c0eSPaolo Bonzini //! type provides the following methods, all of which can be called only while 818e194c0eSPaolo Bonzini //! the BQL is held: 828e194c0eSPaolo Bonzini //! 838e194c0eSPaolo Bonzini //! - For types that implement [`Copy`], the [`get`](BqlCell::get) method 848e194c0eSPaolo Bonzini //! retrieves the current interior value by duplicating it. 858e194c0eSPaolo Bonzini //! - For types that implement [`Default`], the [`take`](BqlCell::take) method 868e194c0eSPaolo Bonzini //! replaces the current interior value with [`Default::default()`] and 878e194c0eSPaolo Bonzini //! returns the replaced value. 888e194c0eSPaolo Bonzini //! - All types have: 898e194c0eSPaolo Bonzini //! - [`replace`](BqlCell::replace): replaces the current interior value and 908e194c0eSPaolo Bonzini //! returns the replaced value. 918e194c0eSPaolo Bonzini //! - [`set`](BqlCell::set): this method replaces the interior value, 928e194c0eSPaolo Bonzini //! dropping the replaced value. 93*c596199fSPaolo Bonzini //! 94*c596199fSPaolo Bonzini //! ## `BqlRefCell<T>` 95*c596199fSPaolo Bonzini //! 96*c596199fSPaolo Bonzini //! [`BqlRefCell<T>`] uses Rust's lifetimes to implement "dynamic borrowing", a 97*c596199fSPaolo Bonzini //! process whereby one can claim temporary, exclusive, mutable access to the 98*c596199fSPaolo Bonzini //! inner value: 99*c596199fSPaolo Bonzini //! 100*c596199fSPaolo Bonzini //! ```ignore 101*c596199fSPaolo Bonzini //! fn clear_interrupts(&self, val: u32) { 102*c596199fSPaolo Bonzini //! // A mutable borrow gives read-write access to the registers 103*c596199fSPaolo Bonzini //! let mut regs = self.registers.borrow_mut(); 104*c596199fSPaolo Bonzini //! let old = regs.interrupt_status(); 105*c596199fSPaolo Bonzini //! regs.update_interrupt_status(old & !val); 106*c596199fSPaolo Bonzini //! } 107*c596199fSPaolo Bonzini //! ``` 108*c596199fSPaolo Bonzini //! 109*c596199fSPaolo Bonzini //! Borrows for `BqlRefCell<T>`s are tracked at _runtime_, unlike Rust's native 110*c596199fSPaolo Bonzini //! reference types which are entirely tracked statically, at compile time. 111*c596199fSPaolo Bonzini //! Multiple immutable borrows are allowed via [`borrow`](BqlRefCell::borrow), 112*c596199fSPaolo Bonzini //! or a single mutable borrow via [`borrow_mut`](BqlRefCell::borrow_mut). The 113*c596199fSPaolo Bonzini //! thread will panic if these rules are violated or if the BQL is not held. 1148e194c0eSPaolo Bonzini 115*c596199fSPaolo Bonzini use std::{ 116*c596199fSPaolo Bonzini cell::{Cell, UnsafeCell}, 117*c596199fSPaolo Bonzini cmp::Ordering, 118*c596199fSPaolo Bonzini fmt, 119*c596199fSPaolo Bonzini marker::PhantomData, 120*c596199fSPaolo Bonzini mem, 121*c596199fSPaolo Bonzini ops::{Deref, DerefMut}, 122*c596199fSPaolo Bonzini ptr::NonNull, 123*c596199fSPaolo Bonzini }; 1248e194c0eSPaolo Bonzini 1258e194c0eSPaolo Bonzini use crate::bindings; 1268e194c0eSPaolo Bonzini 1278e194c0eSPaolo Bonzini // TODO: When building doctests do not include the actual BQL, because cargo 1288e194c0eSPaolo Bonzini // does not know how to link them to libqemuutil. This can be fixed by 1298e194c0eSPaolo Bonzini // running rustdoc from "meson test" instead of relying on cargo. 1308e194c0eSPaolo Bonzini pub fn bql_locked() -> bool { 1318e194c0eSPaolo Bonzini // SAFETY: the function does nothing but return a thread-local bool 1328e194c0eSPaolo Bonzini !cfg!(MESON) || unsafe { bindings::bql_locked() } 1338e194c0eSPaolo Bonzini } 1348e194c0eSPaolo Bonzini 135*c596199fSPaolo Bonzini fn bql_block_unlock(increase: bool) { 136*c596199fSPaolo Bonzini if cfg!(MESON) { 137*c596199fSPaolo Bonzini // SAFETY: this only adjusts a counter 138*c596199fSPaolo Bonzini unsafe { 139*c596199fSPaolo Bonzini bindings::bql_block_unlock(increase); 140*c596199fSPaolo Bonzini } 141*c596199fSPaolo Bonzini } 142*c596199fSPaolo Bonzini } 143*c596199fSPaolo Bonzini 1448e194c0eSPaolo Bonzini /// A mutable memory location that is protected by the Big QEMU Lock. 1458e194c0eSPaolo Bonzini /// 1468e194c0eSPaolo Bonzini /// # Memory layout 1478e194c0eSPaolo Bonzini /// 1488e194c0eSPaolo Bonzini /// `BqlCell<T>` has the same in-memory representation as its inner type `T`. 1498e194c0eSPaolo Bonzini #[repr(transparent)] 1508e194c0eSPaolo Bonzini pub struct BqlCell<T> { 1518e194c0eSPaolo Bonzini value: UnsafeCell<T>, 1528e194c0eSPaolo Bonzini } 1538e194c0eSPaolo Bonzini 1548e194c0eSPaolo Bonzini // SAFETY: Same as for std::sync::Mutex. In the end this *is* a Mutex, 1558e194c0eSPaolo Bonzini // except it is stored out-of-line 1568e194c0eSPaolo Bonzini unsafe impl<T: Send> Send for BqlCell<T> {} 1578e194c0eSPaolo Bonzini unsafe impl<T: Send> Sync for BqlCell<T> {} 1588e194c0eSPaolo Bonzini 1598e194c0eSPaolo Bonzini impl<T: Copy> Clone for BqlCell<T> { 1608e194c0eSPaolo Bonzini #[inline] 1618e194c0eSPaolo Bonzini fn clone(&self) -> BqlCell<T> { 1628e194c0eSPaolo Bonzini BqlCell::new(self.get()) 1638e194c0eSPaolo Bonzini } 1648e194c0eSPaolo Bonzini } 1658e194c0eSPaolo Bonzini 1668e194c0eSPaolo Bonzini impl<T: Default> Default for BqlCell<T> { 1678e194c0eSPaolo Bonzini /// Creates a `BqlCell<T>`, with the `Default` value for T. 1688e194c0eSPaolo Bonzini #[inline] 1698e194c0eSPaolo Bonzini fn default() -> BqlCell<T> { 1708e194c0eSPaolo Bonzini BqlCell::new(Default::default()) 1718e194c0eSPaolo Bonzini } 1728e194c0eSPaolo Bonzini } 1738e194c0eSPaolo Bonzini 1748e194c0eSPaolo Bonzini impl<T: PartialEq + Copy> PartialEq for BqlCell<T> { 1758e194c0eSPaolo Bonzini #[inline] 1768e194c0eSPaolo Bonzini fn eq(&self, other: &BqlCell<T>) -> bool { 1778e194c0eSPaolo Bonzini self.get() == other.get() 1788e194c0eSPaolo Bonzini } 1798e194c0eSPaolo Bonzini } 1808e194c0eSPaolo Bonzini 1818e194c0eSPaolo Bonzini impl<T: Eq + Copy> Eq for BqlCell<T> {} 1828e194c0eSPaolo Bonzini 1838e194c0eSPaolo Bonzini impl<T: PartialOrd + Copy> PartialOrd for BqlCell<T> { 1848e194c0eSPaolo Bonzini #[inline] 1858e194c0eSPaolo Bonzini fn partial_cmp(&self, other: &BqlCell<T>) -> Option<Ordering> { 1868e194c0eSPaolo Bonzini self.get().partial_cmp(&other.get()) 1878e194c0eSPaolo Bonzini } 1888e194c0eSPaolo Bonzini } 1898e194c0eSPaolo Bonzini 1908e194c0eSPaolo Bonzini impl<T: Ord + Copy> Ord for BqlCell<T> { 1918e194c0eSPaolo Bonzini #[inline] 1928e194c0eSPaolo Bonzini fn cmp(&self, other: &BqlCell<T>) -> Ordering { 1938e194c0eSPaolo Bonzini self.get().cmp(&other.get()) 1948e194c0eSPaolo Bonzini } 1958e194c0eSPaolo Bonzini } 1968e194c0eSPaolo Bonzini 1978e194c0eSPaolo Bonzini impl<T> From<T> for BqlCell<T> { 1988e194c0eSPaolo Bonzini /// Creates a new `BqlCell<T>` containing the given value. 1998e194c0eSPaolo Bonzini fn from(t: T) -> BqlCell<T> { 2008e194c0eSPaolo Bonzini BqlCell::new(t) 2018e194c0eSPaolo Bonzini } 2028e194c0eSPaolo Bonzini } 2038e194c0eSPaolo Bonzini 2048e194c0eSPaolo Bonzini impl<T: fmt::Debug + Copy> fmt::Debug for BqlCell<T> { 2058e194c0eSPaolo Bonzini fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 2068e194c0eSPaolo Bonzini self.get().fmt(f) 2078e194c0eSPaolo Bonzini } 2088e194c0eSPaolo Bonzini } 2098e194c0eSPaolo Bonzini 2108e194c0eSPaolo Bonzini impl<T: fmt::Display + Copy> fmt::Display for BqlCell<T> { 2118e194c0eSPaolo Bonzini fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 2128e194c0eSPaolo Bonzini self.get().fmt(f) 2138e194c0eSPaolo Bonzini } 2148e194c0eSPaolo Bonzini } 2158e194c0eSPaolo Bonzini 2168e194c0eSPaolo Bonzini impl<T> BqlCell<T> { 2178e194c0eSPaolo Bonzini /// Creates a new `BqlCell` containing the given value. 2188e194c0eSPaolo Bonzini /// 2198e194c0eSPaolo Bonzini /// # Examples 2208e194c0eSPaolo Bonzini /// 2218e194c0eSPaolo Bonzini /// ``` 2228e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 2238e194c0eSPaolo Bonzini /// 2248e194c0eSPaolo Bonzini /// let c = BqlCell::new(5); 2258e194c0eSPaolo Bonzini /// ``` 2268e194c0eSPaolo Bonzini #[inline] 2278e194c0eSPaolo Bonzini pub const fn new(value: T) -> BqlCell<T> { 2288e194c0eSPaolo Bonzini BqlCell { 2298e194c0eSPaolo Bonzini value: UnsafeCell::new(value), 2308e194c0eSPaolo Bonzini } 2318e194c0eSPaolo Bonzini } 2328e194c0eSPaolo Bonzini 2338e194c0eSPaolo Bonzini /// Sets the contained value. 2348e194c0eSPaolo Bonzini /// 2358e194c0eSPaolo Bonzini /// # Examples 2368e194c0eSPaolo Bonzini /// 2378e194c0eSPaolo Bonzini /// ``` 2388e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 2398e194c0eSPaolo Bonzini /// 2408e194c0eSPaolo Bonzini /// let c = BqlCell::new(5); 2418e194c0eSPaolo Bonzini /// 2428e194c0eSPaolo Bonzini /// c.set(10); 2438e194c0eSPaolo Bonzini /// ``` 2448e194c0eSPaolo Bonzini #[inline] 2458e194c0eSPaolo Bonzini pub fn set(&self, val: T) { 2468e194c0eSPaolo Bonzini self.replace(val); 2478e194c0eSPaolo Bonzini } 2488e194c0eSPaolo Bonzini 2498e194c0eSPaolo Bonzini /// Replaces the contained value with `val`, and returns the old contained 2508e194c0eSPaolo Bonzini /// value. 2518e194c0eSPaolo Bonzini /// 2528e194c0eSPaolo Bonzini /// # Examples 2538e194c0eSPaolo Bonzini /// 2548e194c0eSPaolo Bonzini /// ``` 2558e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 2568e194c0eSPaolo Bonzini /// 2578e194c0eSPaolo Bonzini /// let cell = BqlCell::new(5); 2588e194c0eSPaolo Bonzini /// assert_eq!(cell.get(), 5); 2598e194c0eSPaolo Bonzini /// assert_eq!(cell.replace(10), 5); 2608e194c0eSPaolo Bonzini /// assert_eq!(cell.get(), 10); 2618e194c0eSPaolo Bonzini /// ``` 2628e194c0eSPaolo Bonzini #[inline] 2638e194c0eSPaolo Bonzini pub fn replace(&self, val: T) -> T { 2648e194c0eSPaolo Bonzini assert!(bql_locked()); 2658e194c0eSPaolo Bonzini // SAFETY: This can cause data races if called from multiple threads, 2668e194c0eSPaolo Bonzini // but it won't happen as long as C code accesses the value 2678e194c0eSPaolo Bonzini // under BQL protection only. 2688e194c0eSPaolo Bonzini mem::replace(unsafe { &mut *self.value.get() }, val) 2698e194c0eSPaolo Bonzini } 2708e194c0eSPaolo Bonzini 2718e194c0eSPaolo Bonzini /// Unwraps the value, consuming the cell. 2728e194c0eSPaolo Bonzini /// 2738e194c0eSPaolo Bonzini /// # Examples 2748e194c0eSPaolo Bonzini /// 2758e194c0eSPaolo Bonzini /// ``` 2768e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 2778e194c0eSPaolo Bonzini /// 2788e194c0eSPaolo Bonzini /// let c = BqlCell::new(5); 2798e194c0eSPaolo Bonzini /// let five = c.into_inner(); 2808e194c0eSPaolo Bonzini /// 2818e194c0eSPaolo Bonzini /// assert_eq!(five, 5); 2828e194c0eSPaolo Bonzini /// ``` 2838e194c0eSPaolo Bonzini pub fn into_inner(self) -> T { 2848e194c0eSPaolo Bonzini assert!(bql_locked()); 2858e194c0eSPaolo Bonzini self.value.into_inner() 2868e194c0eSPaolo Bonzini } 2878e194c0eSPaolo Bonzini } 2888e194c0eSPaolo Bonzini 2898e194c0eSPaolo Bonzini impl<T: Copy> BqlCell<T> { 2908e194c0eSPaolo Bonzini /// Returns a copy of the contained value. 2918e194c0eSPaolo Bonzini /// 2928e194c0eSPaolo Bonzini /// # Examples 2938e194c0eSPaolo Bonzini /// 2948e194c0eSPaolo Bonzini /// ``` 2958e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 2968e194c0eSPaolo Bonzini /// 2978e194c0eSPaolo Bonzini /// let c = BqlCell::new(5); 2988e194c0eSPaolo Bonzini /// 2998e194c0eSPaolo Bonzini /// let five = c.get(); 3008e194c0eSPaolo Bonzini /// ``` 3018e194c0eSPaolo Bonzini #[inline] 3028e194c0eSPaolo Bonzini pub fn get(&self) -> T { 3038e194c0eSPaolo Bonzini assert!(bql_locked()); 3048e194c0eSPaolo Bonzini // SAFETY: This can cause data races if called from multiple threads, 3058e194c0eSPaolo Bonzini // but it won't happen as long as C code accesses the value 3068e194c0eSPaolo Bonzini // under BQL protection only. 3078e194c0eSPaolo Bonzini unsafe { *self.value.get() } 3088e194c0eSPaolo Bonzini } 3098e194c0eSPaolo Bonzini } 3108e194c0eSPaolo Bonzini 3118e194c0eSPaolo Bonzini impl<T> BqlCell<T> { 3128e194c0eSPaolo Bonzini /// Returns a raw pointer to the underlying data in this cell. 3138e194c0eSPaolo Bonzini /// 3148e194c0eSPaolo Bonzini /// # Examples 3158e194c0eSPaolo Bonzini /// 3168e194c0eSPaolo Bonzini /// ``` 3178e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 3188e194c0eSPaolo Bonzini /// 3198e194c0eSPaolo Bonzini /// let c = BqlCell::new(5); 3208e194c0eSPaolo Bonzini /// 3218e194c0eSPaolo Bonzini /// let ptr = c.as_ptr(); 3228e194c0eSPaolo Bonzini /// ``` 3238e194c0eSPaolo Bonzini #[inline] 3248e194c0eSPaolo Bonzini pub const fn as_ptr(&self) -> *mut T { 3258e194c0eSPaolo Bonzini self.value.get() 3268e194c0eSPaolo Bonzini } 3278e194c0eSPaolo Bonzini } 3288e194c0eSPaolo Bonzini 3298e194c0eSPaolo Bonzini impl<T: Default> BqlCell<T> { 3308e194c0eSPaolo Bonzini /// Takes the value of the cell, leaving `Default::default()` in its place. 3318e194c0eSPaolo Bonzini /// 3328e194c0eSPaolo Bonzini /// # Examples 3338e194c0eSPaolo Bonzini /// 3348e194c0eSPaolo Bonzini /// ``` 3358e194c0eSPaolo Bonzini /// use qemu_api::cell::BqlCell; 3368e194c0eSPaolo Bonzini /// 3378e194c0eSPaolo Bonzini /// let c = BqlCell::new(5); 3388e194c0eSPaolo Bonzini /// let five = c.take(); 3398e194c0eSPaolo Bonzini /// 3408e194c0eSPaolo Bonzini /// assert_eq!(five, 5); 3418e194c0eSPaolo Bonzini /// assert_eq!(c.into_inner(), 0); 3428e194c0eSPaolo Bonzini /// ``` 3438e194c0eSPaolo Bonzini pub fn take(&self) -> T { 3448e194c0eSPaolo Bonzini self.replace(Default::default()) 3458e194c0eSPaolo Bonzini } 3468e194c0eSPaolo Bonzini } 347*c596199fSPaolo Bonzini 348*c596199fSPaolo Bonzini /// A mutable memory location with dynamically checked borrow rules, 349*c596199fSPaolo Bonzini /// protected by the Big QEMU Lock. 350*c596199fSPaolo Bonzini /// 351*c596199fSPaolo Bonzini /// See the [module-level documentation](self) for more. 352*c596199fSPaolo Bonzini /// 353*c596199fSPaolo Bonzini /// # Memory layout 354*c596199fSPaolo Bonzini /// 355*c596199fSPaolo Bonzini /// `BqlRefCell<T>` starts with the same in-memory representation as its 356*c596199fSPaolo Bonzini /// inner type `T`. 357*c596199fSPaolo Bonzini #[repr(C)] 358*c596199fSPaolo Bonzini pub struct BqlRefCell<T> { 359*c596199fSPaolo Bonzini // It is important that this is the first field (which is not the case 360*c596199fSPaolo Bonzini // for std::cell::BqlRefCell), so that we can use offset_of! on it. 361*c596199fSPaolo Bonzini // UnsafeCell and repr(C) both prevent usage of niches. 362*c596199fSPaolo Bonzini value: UnsafeCell<T>, 363*c596199fSPaolo Bonzini borrow: Cell<BorrowFlag>, 364*c596199fSPaolo Bonzini // Stores the location of the earliest currently active borrow. 365*c596199fSPaolo Bonzini // This gets updated whenever we go from having zero borrows 366*c596199fSPaolo Bonzini // to having a single borrow. When a borrow occurs, this gets included 367*c596199fSPaolo Bonzini // in the panic message 368*c596199fSPaolo Bonzini #[cfg(feature = "debug_cell")] 369*c596199fSPaolo Bonzini borrowed_at: Cell<Option<&'static std::panic::Location<'static>>>, 370*c596199fSPaolo Bonzini } 371*c596199fSPaolo Bonzini 372*c596199fSPaolo Bonzini // Positive values represent the number of `BqlRef` active. Negative values 373*c596199fSPaolo Bonzini // represent the number of `BqlRefMut` active. Right now QEMU's implementation 374*c596199fSPaolo Bonzini // does not allow to create `BqlRefMut`s that refer to distinct, nonoverlapping 375*c596199fSPaolo Bonzini // components of a `BqlRefCell` (e.g., different ranges of a slice). 376*c596199fSPaolo Bonzini // 377*c596199fSPaolo Bonzini // `BqlRef` and `BqlRefMut` are both two words in size, and so there will likely 378*c596199fSPaolo Bonzini // never be enough `BqlRef`s or `BqlRefMut`s in existence to overflow half of 379*c596199fSPaolo Bonzini // the `usize` range. Thus, a `BorrowFlag` will probably never overflow or 380*c596199fSPaolo Bonzini // underflow. However, this is not a guarantee, as a pathological program could 381*c596199fSPaolo Bonzini // repeatedly create and then mem::forget `BqlRef`s or `BqlRefMut`s. Thus, all 382*c596199fSPaolo Bonzini // code must explicitly check for overflow and underflow in order to avoid 383*c596199fSPaolo Bonzini // unsafety, or at least behave correctly in the event that overflow or 384*c596199fSPaolo Bonzini // underflow happens (e.g., see BorrowRef::new). 385*c596199fSPaolo Bonzini type BorrowFlag = isize; 386*c596199fSPaolo Bonzini const UNUSED: BorrowFlag = 0; 387*c596199fSPaolo Bonzini 388*c596199fSPaolo Bonzini #[inline(always)] 389*c596199fSPaolo Bonzini const fn is_writing(x: BorrowFlag) -> bool { 390*c596199fSPaolo Bonzini x < UNUSED 391*c596199fSPaolo Bonzini } 392*c596199fSPaolo Bonzini 393*c596199fSPaolo Bonzini #[inline(always)] 394*c596199fSPaolo Bonzini const fn is_reading(x: BorrowFlag) -> bool { 395*c596199fSPaolo Bonzini x > UNUSED 396*c596199fSPaolo Bonzini } 397*c596199fSPaolo Bonzini 398*c596199fSPaolo Bonzini impl<T> BqlRefCell<T> { 399*c596199fSPaolo Bonzini /// Creates a new `BqlRefCell` containing `value`. 400*c596199fSPaolo Bonzini /// 401*c596199fSPaolo Bonzini /// # Examples 402*c596199fSPaolo Bonzini /// 403*c596199fSPaolo Bonzini /// ``` 404*c596199fSPaolo Bonzini /// use qemu_api::cell::BqlRefCell; 405*c596199fSPaolo Bonzini /// 406*c596199fSPaolo Bonzini /// let c = BqlRefCell::new(5); 407*c596199fSPaolo Bonzini /// ``` 408*c596199fSPaolo Bonzini #[inline] 409*c596199fSPaolo Bonzini pub const fn new(value: T) -> BqlRefCell<T> { 410*c596199fSPaolo Bonzini BqlRefCell { 411*c596199fSPaolo Bonzini value: UnsafeCell::new(value), 412*c596199fSPaolo Bonzini borrow: Cell::new(UNUSED), 413*c596199fSPaolo Bonzini #[cfg(feature = "debug_cell")] 414*c596199fSPaolo Bonzini borrowed_at: Cell::new(None), 415*c596199fSPaolo Bonzini } 416*c596199fSPaolo Bonzini } 417*c596199fSPaolo Bonzini } 418*c596199fSPaolo Bonzini 419*c596199fSPaolo Bonzini // This ensures the panicking code is outlined from `borrow_mut` for 420*c596199fSPaolo Bonzini // `BqlRefCell`. 421*c596199fSPaolo Bonzini #[inline(never)] 422*c596199fSPaolo Bonzini #[cold] 423*c596199fSPaolo Bonzini #[cfg(feature = "debug_cell")] 424*c596199fSPaolo Bonzini fn panic_already_borrowed(source: &Cell<Option<&'static std::panic::Location<'static>>>) -> ! { 425*c596199fSPaolo Bonzini // If a borrow occurred, then we must already have an outstanding borrow, 426*c596199fSPaolo Bonzini // so `borrowed_at` will be `Some` 427*c596199fSPaolo Bonzini panic!("already borrowed at {:?}", source.take().unwrap()) 428*c596199fSPaolo Bonzini } 429*c596199fSPaolo Bonzini 430*c596199fSPaolo Bonzini #[inline(never)] 431*c596199fSPaolo Bonzini #[cold] 432*c596199fSPaolo Bonzini #[cfg(not(feature = "debug_cell"))] 433*c596199fSPaolo Bonzini fn panic_already_borrowed() -> ! { 434*c596199fSPaolo Bonzini panic!("already borrowed") 435*c596199fSPaolo Bonzini } 436*c596199fSPaolo Bonzini 437*c596199fSPaolo Bonzini impl<T> BqlRefCell<T> { 438*c596199fSPaolo Bonzini #[inline] 439*c596199fSPaolo Bonzini #[allow(clippy::unused_self)] 440*c596199fSPaolo Bonzini fn panic_already_borrowed(&self) -> ! { 441*c596199fSPaolo Bonzini #[cfg(feature = "debug_cell")] 442*c596199fSPaolo Bonzini { 443*c596199fSPaolo Bonzini panic_already_borrowed(&self.borrowed_at) 444*c596199fSPaolo Bonzini } 445*c596199fSPaolo Bonzini #[cfg(not(feature = "debug_cell"))] 446*c596199fSPaolo Bonzini { 447*c596199fSPaolo Bonzini panic_already_borrowed() 448*c596199fSPaolo Bonzini } 449*c596199fSPaolo Bonzini } 450*c596199fSPaolo Bonzini 451*c596199fSPaolo Bonzini /// Immutably borrows the wrapped value. 452*c596199fSPaolo Bonzini /// 453*c596199fSPaolo Bonzini /// The borrow lasts until the returned `BqlRef` exits scope. Multiple 454*c596199fSPaolo Bonzini /// immutable borrows can be taken out at the same time. 455*c596199fSPaolo Bonzini /// 456*c596199fSPaolo Bonzini /// # Panics 457*c596199fSPaolo Bonzini /// 458*c596199fSPaolo Bonzini /// Panics if the value is currently mutably borrowed. 459*c596199fSPaolo Bonzini /// 460*c596199fSPaolo Bonzini /// # Examples 461*c596199fSPaolo Bonzini /// 462*c596199fSPaolo Bonzini /// ``` 463*c596199fSPaolo Bonzini /// use qemu_api::cell::BqlRefCell; 464*c596199fSPaolo Bonzini /// 465*c596199fSPaolo Bonzini /// let c = BqlRefCell::new(5); 466*c596199fSPaolo Bonzini /// 467*c596199fSPaolo Bonzini /// let borrowed_five = c.borrow(); 468*c596199fSPaolo Bonzini /// let borrowed_five2 = c.borrow(); 469*c596199fSPaolo Bonzini /// ``` 470*c596199fSPaolo Bonzini /// 471*c596199fSPaolo Bonzini /// An example of panic: 472*c596199fSPaolo Bonzini /// 473*c596199fSPaolo Bonzini /// ```should_panic 474*c596199fSPaolo Bonzini /// use qemu_api::cell::BqlRefCell; 475*c596199fSPaolo Bonzini /// 476*c596199fSPaolo Bonzini /// let c = BqlRefCell::new(5); 477*c596199fSPaolo Bonzini /// 478*c596199fSPaolo Bonzini /// let m = c.borrow_mut(); 479*c596199fSPaolo Bonzini /// let b = c.borrow(); // this causes a panic 480*c596199fSPaolo Bonzini /// ``` 481*c596199fSPaolo Bonzini #[inline] 482*c596199fSPaolo Bonzini #[track_caller] 483*c596199fSPaolo Bonzini pub fn borrow(&self) -> BqlRef<'_, T> { 484*c596199fSPaolo Bonzini if let Some(b) = BorrowRef::new(&self.borrow) { 485*c596199fSPaolo Bonzini // `borrowed_at` is always the *first* active borrow 486*c596199fSPaolo Bonzini if b.borrow.get() == 1 { 487*c596199fSPaolo Bonzini #[cfg(feature = "debug_cell")] 488*c596199fSPaolo Bonzini self.borrowed_at.set(Some(std::panic::Location::caller())); 489*c596199fSPaolo Bonzini } 490*c596199fSPaolo Bonzini 491*c596199fSPaolo Bonzini bql_block_unlock(true); 492*c596199fSPaolo Bonzini 493*c596199fSPaolo Bonzini // SAFETY: `BorrowRef` ensures that there is only immutable access 494*c596199fSPaolo Bonzini // to the value while borrowed. 495*c596199fSPaolo Bonzini let value = unsafe { NonNull::new_unchecked(self.value.get()) }; 496*c596199fSPaolo Bonzini BqlRef { value, borrow: b } 497*c596199fSPaolo Bonzini } else { 498*c596199fSPaolo Bonzini self.panic_already_borrowed() 499*c596199fSPaolo Bonzini } 500*c596199fSPaolo Bonzini } 501*c596199fSPaolo Bonzini 502*c596199fSPaolo Bonzini /// Mutably borrows the wrapped value. 503*c596199fSPaolo Bonzini /// 504*c596199fSPaolo Bonzini /// The borrow lasts until the returned `BqlRefMut` or all `BqlRefMut`s 505*c596199fSPaolo Bonzini /// derived from it exit scope. The value cannot be borrowed while this 506*c596199fSPaolo Bonzini /// borrow is active. 507*c596199fSPaolo Bonzini /// 508*c596199fSPaolo Bonzini /// # Panics 509*c596199fSPaolo Bonzini /// 510*c596199fSPaolo Bonzini /// Panics if the value is currently borrowed. 511*c596199fSPaolo Bonzini /// 512*c596199fSPaolo Bonzini /// # Examples 513*c596199fSPaolo Bonzini /// 514*c596199fSPaolo Bonzini /// ``` 515*c596199fSPaolo Bonzini /// use qemu_api::cell::BqlRefCell; 516*c596199fSPaolo Bonzini /// 517*c596199fSPaolo Bonzini /// let c = BqlRefCell::new("hello".to_owned()); 518*c596199fSPaolo Bonzini /// 519*c596199fSPaolo Bonzini /// *c.borrow_mut() = "bonjour".to_owned(); 520*c596199fSPaolo Bonzini /// 521*c596199fSPaolo Bonzini /// assert_eq!(&*c.borrow(), "bonjour"); 522*c596199fSPaolo Bonzini /// ``` 523*c596199fSPaolo Bonzini /// 524*c596199fSPaolo Bonzini /// An example of panic: 525*c596199fSPaolo Bonzini /// 526*c596199fSPaolo Bonzini /// ```should_panic 527*c596199fSPaolo Bonzini /// use qemu_api::cell::BqlRefCell; 528*c596199fSPaolo Bonzini /// 529*c596199fSPaolo Bonzini /// let c = BqlRefCell::new(5); 530*c596199fSPaolo Bonzini /// let m = c.borrow(); 531*c596199fSPaolo Bonzini /// 532*c596199fSPaolo Bonzini /// let b = c.borrow_mut(); // this causes a panic 533*c596199fSPaolo Bonzini /// ``` 534*c596199fSPaolo Bonzini #[inline] 535*c596199fSPaolo Bonzini #[track_caller] 536*c596199fSPaolo Bonzini pub fn borrow_mut(&self) -> BqlRefMut<'_, T> { 537*c596199fSPaolo Bonzini if let Some(b) = BorrowRefMut::new(&self.borrow) { 538*c596199fSPaolo Bonzini #[cfg(feature = "debug_cell")] 539*c596199fSPaolo Bonzini { 540*c596199fSPaolo Bonzini self.borrowed_at.set(Some(std::panic::Location::caller())); 541*c596199fSPaolo Bonzini } 542*c596199fSPaolo Bonzini 543*c596199fSPaolo Bonzini // SAFETY: this only adjusts a counter 544*c596199fSPaolo Bonzini bql_block_unlock(true); 545*c596199fSPaolo Bonzini 546*c596199fSPaolo Bonzini // SAFETY: `BorrowRefMut` guarantees unique access. 547*c596199fSPaolo Bonzini let value = unsafe { NonNull::new_unchecked(self.value.get()) }; 548*c596199fSPaolo Bonzini BqlRefMut { 549*c596199fSPaolo Bonzini value, 550*c596199fSPaolo Bonzini _borrow: b, 551*c596199fSPaolo Bonzini marker: PhantomData, 552*c596199fSPaolo Bonzini } 553*c596199fSPaolo Bonzini } else { 554*c596199fSPaolo Bonzini self.panic_already_borrowed() 555*c596199fSPaolo Bonzini } 556*c596199fSPaolo Bonzini } 557*c596199fSPaolo Bonzini 558*c596199fSPaolo Bonzini /// Returns a raw pointer to the underlying data in this cell. 559*c596199fSPaolo Bonzini /// 560*c596199fSPaolo Bonzini /// # Examples 561*c596199fSPaolo Bonzini /// 562*c596199fSPaolo Bonzini /// ``` 563*c596199fSPaolo Bonzini /// use qemu_api::cell::BqlRefCell; 564*c596199fSPaolo Bonzini /// 565*c596199fSPaolo Bonzini /// let c = BqlRefCell::new(5); 566*c596199fSPaolo Bonzini /// 567*c596199fSPaolo Bonzini /// let ptr = c.as_ptr(); 568*c596199fSPaolo Bonzini /// ``` 569*c596199fSPaolo Bonzini #[inline] 570*c596199fSPaolo Bonzini pub const fn as_ptr(&self) -> *mut T { 571*c596199fSPaolo Bonzini self.value.get() 572*c596199fSPaolo Bonzini } 573*c596199fSPaolo Bonzini } 574*c596199fSPaolo Bonzini 575*c596199fSPaolo Bonzini // SAFETY: Same as for std::sync::Mutex. In the end this is a Mutex that is 576*c596199fSPaolo Bonzini // stored out-of-line. Even though BqlRefCell includes Cells, they are 577*c596199fSPaolo Bonzini // themselves protected by the Big QEMU Lock. Furtheremore, the Big QEMU 578*c596199fSPaolo Bonzini // Lock cannot be released while any borrows is active. 579*c596199fSPaolo Bonzini unsafe impl<T> Send for BqlRefCell<T> where T: Send {} 580*c596199fSPaolo Bonzini unsafe impl<T> Sync for BqlRefCell<T> {} 581*c596199fSPaolo Bonzini 582*c596199fSPaolo Bonzini impl<T: Clone> Clone for BqlRefCell<T> { 583*c596199fSPaolo Bonzini /// # Panics 584*c596199fSPaolo Bonzini /// 585*c596199fSPaolo Bonzini /// Panics if the value is currently mutably borrowed. 586*c596199fSPaolo Bonzini #[inline] 587*c596199fSPaolo Bonzini #[track_caller] 588*c596199fSPaolo Bonzini fn clone(&self) -> BqlRefCell<T> { 589*c596199fSPaolo Bonzini BqlRefCell::new(self.borrow().clone()) 590*c596199fSPaolo Bonzini } 591*c596199fSPaolo Bonzini 592*c596199fSPaolo Bonzini /// # Panics 593*c596199fSPaolo Bonzini /// 594*c596199fSPaolo Bonzini /// Panics if `source` is currently mutably borrowed. 595*c596199fSPaolo Bonzini #[inline] 596*c596199fSPaolo Bonzini #[track_caller] 597*c596199fSPaolo Bonzini fn clone_from(&mut self, source: &Self) { 598*c596199fSPaolo Bonzini self.value.get_mut().clone_from(&source.borrow()) 599*c596199fSPaolo Bonzini } 600*c596199fSPaolo Bonzini } 601*c596199fSPaolo Bonzini 602*c596199fSPaolo Bonzini impl<T: Default> Default for BqlRefCell<T> { 603*c596199fSPaolo Bonzini /// Creates a `BqlRefCell<T>`, with the `Default` value for T. 604*c596199fSPaolo Bonzini #[inline] 605*c596199fSPaolo Bonzini fn default() -> BqlRefCell<T> { 606*c596199fSPaolo Bonzini BqlRefCell::new(Default::default()) 607*c596199fSPaolo Bonzini } 608*c596199fSPaolo Bonzini } 609*c596199fSPaolo Bonzini 610*c596199fSPaolo Bonzini impl<T: PartialEq> PartialEq for BqlRefCell<T> { 611*c596199fSPaolo Bonzini /// # Panics 612*c596199fSPaolo Bonzini /// 613*c596199fSPaolo Bonzini /// Panics if the value in either `BqlRefCell` is currently mutably 614*c596199fSPaolo Bonzini /// borrowed. 615*c596199fSPaolo Bonzini #[inline] 616*c596199fSPaolo Bonzini fn eq(&self, other: &BqlRefCell<T>) -> bool { 617*c596199fSPaolo Bonzini *self.borrow() == *other.borrow() 618*c596199fSPaolo Bonzini } 619*c596199fSPaolo Bonzini } 620*c596199fSPaolo Bonzini 621*c596199fSPaolo Bonzini impl<T: Eq> Eq for BqlRefCell<T> {} 622*c596199fSPaolo Bonzini 623*c596199fSPaolo Bonzini impl<T: PartialOrd> PartialOrd for BqlRefCell<T> { 624*c596199fSPaolo Bonzini /// # Panics 625*c596199fSPaolo Bonzini /// 626*c596199fSPaolo Bonzini /// Panics if the value in either `BqlRefCell` is currently mutably 627*c596199fSPaolo Bonzini /// borrowed. 628*c596199fSPaolo Bonzini #[inline] 629*c596199fSPaolo Bonzini fn partial_cmp(&self, other: &BqlRefCell<T>) -> Option<Ordering> { 630*c596199fSPaolo Bonzini self.borrow().partial_cmp(&*other.borrow()) 631*c596199fSPaolo Bonzini } 632*c596199fSPaolo Bonzini } 633*c596199fSPaolo Bonzini 634*c596199fSPaolo Bonzini impl<T: Ord> Ord for BqlRefCell<T> { 635*c596199fSPaolo Bonzini /// # Panics 636*c596199fSPaolo Bonzini /// 637*c596199fSPaolo Bonzini /// Panics if the value in either `BqlRefCell` is currently mutably 638*c596199fSPaolo Bonzini /// borrowed. 639*c596199fSPaolo Bonzini #[inline] 640*c596199fSPaolo Bonzini fn cmp(&self, other: &BqlRefCell<T>) -> Ordering { 641*c596199fSPaolo Bonzini self.borrow().cmp(&*other.borrow()) 642*c596199fSPaolo Bonzini } 643*c596199fSPaolo Bonzini } 644*c596199fSPaolo Bonzini 645*c596199fSPaolo Bonzini impl<T> From<T> for BqlRefCell<T> { 646*c596199fSPaolo Bonzini /// Creates a new `BqlRefCell<T>` containing the given value. 647*c596199fSPaolo Bonzini fn from(t: T) -> BqlRefCell<T> { 648*c596199fSPaolo Bonzini BqlRefCell::new(t) 649*c596199fSPaolo Bonzini } 650*c596199fSPaolo Bonzini } 651*c596199fSPaolo Bonzini 652*c596199fSPaolo Bonzini struct BorrowRef<'b> { 653*c596199fSPaolo Bonzini borrow: &'b Cell<BorrowFlag>, 654*c596199fSPaolo Bonzini } 655*c596199fSPaolo Bonzini 656*c596199fSPaolo Bonzini impl<'b> BorrowRef<'b> { 657*c596199fSPaolo Bonzini #[inline] 658*c596199fSPaolo Bonzini fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> { 659*c596199fSPaolo Bonzini let b = borrow.get().wrapping_add(1); 660*c596199fSPaolo Bonzini if !is_reading(b) { 661*c596199fSPaolo Bonzini // Incrementing borrow can result in a non-reading value (<= 0) in these cases: 662*c596199fSPaolo Bonzini // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read 663*c596199fSPaolo Bonzini // borrow due to Rust's reference aliasing rules 664*c596199fSPaolo Bonzini // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed 665*c596199fSPaolo Bonzini // into isize::MIN (the max amount of writing borrows) so we can't allow an 666*c596199fSPaolo Bonzini // additional read borrow because isize can't represent so many read borrows 667*c596199fSPaolo Bonzini // (this can only happen if you mem::forget more than a small constant amount 668*c596199fSPaolo Bonzini // of `BqlRef`s, which is not good practice) 669*c596199fSPaolo Bonzini None 670*c596199fSPaolo Bonzini } else { 671*c596199fSPaolo Bonzini // Incrementing borrow can result in a reading value (> 0) in these cases: 672*c596199fSPaolo Bonzini // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read 673*c596199fSPaolo Bonzini // borrow 674*c596199fSPaolo Bonzini // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize is 675*c596199fSPaolo Bonzini // large enough to represent having one more read borrow 676*c596199fSPaolo Bonzini borrow.set(b); 677*c596199fSPaolo Bonzini Some(BorrowRef { borrow }) 678*c596199fSPaolo Bonzini } 679*c596199fSPaolo Bonzini } 680*c596199fSPaolo Bonzini } 681*c596199fSPaolo Bonzini 682*c596199fSPaolo Bonzini impl Drop for BorrowRef<'_> { 683*c596199fSPaolo Bonzini #[inline] 684*c596199fSPaolo Bonzini fn drop(&mut self) { 685*c596199fSPaolo Bonzini let borrow = self.borrow.get(); 686*c596199fSPaolo Bonzini debug_assert!(is_reading(borrow)); 687*c596199fSPaolo Bonzini self.borrow.set(borrow - 1); 688*c596199fSPaolo Bonzini bql_block_unlock(false) 689*c596199fSPaolo Bonzini } 690*c596199fSPaolo Bonzini } 691*c596199fSPaolo Bonzini 692*c596199fSPaolo Bonzini impl Clone for BorrowRef<'_> { 693*c596199fSPaolo Bonzini #[inline] 694*c596199fSPaolo Bonzini fn clone(&self) -> Self { 695*c596199fSPaolo Bonzini BorrowRef::new(self.borrow).unwrap() 696*c596199fSPaolo Bonzini } 697*c596199fSPaolo Bonzini } 698*c596199fSPaolo Bonzini 699*c596199fSPaolo Bonzini /// Wraps a borrowed reference to a value in a `BqlRefCell` box. 700*c596199fSPaolo Bonzini /// A wrapper type for an immutably borrowed value from a `BqlRefCell<T>`. 701*c596199fSPaolo Bonzini /// 702*c596199fSPaolo Bonzini /// See the [module-level documentation](self) for more. 703*c596199fSPaolo Bonzini pub struct BqlRef<'b, T: 'b> { 704*c596199fSPaolo Bonzini // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a 705*c596199fSPaolo Bonzini // `BqlRef` argument doesn't hold immutability for its whole scope, only until it drops. 706*c596199fSPaolo Bonzini // `NonNull` is also covariant over `T`, just like we would have with `&T`. 707*c596199fSPaolo Bonzini value: NonNull<T>, 708*c596199fSPaolo Bonzini borrow: BorrowRef<'b>, 709*c596199fSPaolo Bonzini } 710*c596199fSPaolo Bonzini 711*c596199fSPaolo Bonzini impl<T> Deref for BqlRef<'_, T> { 712*c596199fSPaolo Bonzini type Target = T; 713*c596199fSPaolo Bonzini 714*c596199fSPaolo Bonzini #[inline] 715*c596199fSPaolo Bonzini fn deref(&self) -> &T { 716*c596199fSPaolo Bonzini // SAFETY: the value is accessible as long as we hold our borrow. 717*c596199fSPaolo Bonzini unsafe { self.value.as_ref() } 718*c596199fSPaolo Bonzini } 719*c596199fSPaolo Bonzini } 720*c596199fSPaolo Bonzini 721*c596199fSPaolo Bonzini impl<'b, T> BqlRef<'b, T> { 722*c596199fSPaolo Bonzini /// Copies a `BqlRef`. 723*c596199fSPaolo Bonzini /// 724*c596199fSPaolo Bonzini /// The `BqlRefCell` is already immutably borrowed, so this cannot fail. 725*c596199fSPaolo Bonzini /// 726*c596199fSPaolo Bonzini /// This is an associated function that needs to be used as 727*c596199fSPaolo Bonzini /// `BqlRef::clone(...)`. A `Clone` implementation or a method would 728*c596199fSPaolo Bonzini /// interfere with the widespread use of `r.borrow().clone()` to clone 729*c596199fSPaolo Bonzini /// the contents of a `BqlRefCell`. 730*c596199fSPaolo Bonzini #[must_use] 731*c596199fSPaolo Bonzini #[inline] 732*c596199fSPaolo Bonzini #[allow(clippy::should_implement_trait)] 733*c596199fSPaolo Bonzini pub fn clone(orig: &BqlRef<'b, T>) -> BqlRef<'b, T> { 734*c596199fSPaolo Bonzini BqlRef { 735*c596199fSPaolo Bonzini value: orig.value, 736*c596199fSPaolo Bonzini borrow: orig.borrow.clone(), 737*c596199fSPaolo Bonzini } 738*c596199fSPaolo Bonzini } 739*c596199fSPaolo Bonzini } 740*c596199fSPaolo Bonzini 741*c596199fSPaolo Bonzini impl<T: fmt::Debug> fmt::Debug for BqlRef<'_, T> { 742*c596199fSPaolo Bonzini fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 743*c596199fSPaolo Bonzini (**self).fmt(f) 744*c596199fSPaolo Bonzini } 745*c596199fSPaolo Bonzini } 746*c596199fSPaolo Bonzini 747*c596199fSPaolo Bonzini impl<T: fmt::Display> fmt::Display for BqlRef<'_, T> { 748*c596199fSPaolo Bonzini fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 749*c596199fSPaolo Bonzini (**self).fmt(f) 750*c596199fSPaolo Bonzini } 751*c596199fSPaolo Bonzini } 752*c596199fSPaolo Bonzini 753*c596199fSPaolo Bonzini struct BorrowRefMut<'b> { 754*c596199fSPaolo Bonzini borrow: &'b Cell<BorrowFlag>, 755*c596199fSPaolo Bonzini } 756*c596199fSPaolo Bonzini 757*c596199fSPaolo Bonzini impl<'b> BorrowRefMut<'b> { 758*c596199fSPaolo Bonzini #[inline] 759*c596199fSPaolo Bonzini fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> { 760*c596199fSPaolo Bonzini // There must currently be no existing references when borrow_mut() is 761*c596199fSPaolo Bonzini // called, so we explicitly only allow going from UNUSED to UNUSED - 1. 762*c596199fSPaolo Bonzini match borrow.get() { 763*c596199fSPaolo Bonzini UNUSED => { 764*c596199fSPaolo Bonzini borrow.set(UNUSED - 1); 765*c596199fSPaolo Bonzini Some(BorrowRefMut { borrow }) 766*c596199fSPaolo Bonzini } 767*c596199fSPaolo Bonzini _ => None, 768*c596199fSPaolo Bonzini } 769*c596199fSPaolo Bonzini } 770*c596199fSPaolo Bonzini } 771*c596199fSPaolo Bonzini 772*c596199fSPaolo Bonzini impl Drop for BorrowRefMut<'_> { 773*c596199fSPaolo Bonzini #[inline] 774*c596199fSPaolo Bonzini fn drop(&mut self) { 775*c596199fSPaolo Bonzini let borrow = self.borrow.get(); 776*c596199fSPaolo Bonzini debug_assert!(is_writing(borrow)); 777*c596199fSPaolo Bonzini self.borrow.set(borrow + 1); 778*c596199fSPaolo Bonzini bql_block_unlock(false) 779*c596199fSPaolo Bonzini } 780*c596199fSPaolo Bonzini } 781*c596199fSPaolo Bonzini 782*c596199fSPaolo Bonzini /// A wrapper type for a mutably borrowed value from a `BqlRefCell<T>`. 783*c596199fSPaolo Bonzini /// 784*c596199fSPaolo Bonzini /// See the [module-level documentation](self) for more. 785*c596199fSPaolo Bonzini pub struct BqlRefMut<'b, T: 'b> { 786*c596199fSPaolo Bonzini // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a 787*c596199fSPaolo Bonzini // `BqlRefMut` argument doesn't hold exclusivity for its whole scope, only until it drops. 788*c596199fSPaolo Bonzini value: NonNull<T>, 789*c596199fSPaolo Bonzini _borrow: BorrowRefMut<'b>, 790*c596199fSPaolo Bonzini // `NonNull` is covariant over `T`, so we need to reintroduce invariance. 791*c596199fSPaolo Bonzini marker: PhantomData<&'b mut T>, 792*c596199fSPaolo Bonzini } 793*c596199fSPaolo Bonzini 794*c596199fSPaolo Bonzini impl<T> Deref for BqlRefMut<'_, T> { 795*c596199fSPaolo Bonzini type Target = T; 796*c596199fSPaolo Bonzini 797*c596199fSPaolo Bonzini #[inline] 798*c596199fSPaolo Bonzini fn deref(&self) -> &T { 799*c596199fSPaolo Bonzini // SAFETY: the value is accessible as long as we hold our borrow. 800*c596199fSPaolo Bonzini unsafe { self.value.as_ref() } 801*c596199fSPaolo Bonzini } 802*c596199fSPaolo Bonzini } 803*c596199fSPaolo Bonzini 804*c596199fSPaolo Bonzini impl<T> DerefMut for BqlRefMut<'_, T> { 805*c596199fSPaolo Bonzini #[inline] 806*c596199fSPaolo Bonzini fn deref_mut(&mut self) -> &mut T { 807*c596199fSPaolo Bonzini // SAFETY: the value is accessible as long as we hold our borrow. 808*c596199fSPaolo Bonzini unsafe { self.value.as_mut() } 809*c596199fSPaolo Bonzini } 810*c596199fSPaolo Bonzini } 811*c596199fSPaolo Bonzini 812*c596199fSPaolo Bonzini impl<T: fmt::Debug> fmt::Debug for BqlRefMut<'_, T> { 813*c596199fSPaolo Bonzini fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 814*c596199fSPaolo Bonzini (**self).fmt(f) 815*c596199fSPaolo Bonzini } 816*c596199fSPaolo Bonzini } 817*c596199fSPaolo Bonzini 818*c596199fSPaolo Bonzini impl<T: fmt::Display> fmt::Display for BqlRefMut<'_, T> { 819*c596199fSPaolo Bonzini fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 820*c596199fSPaolo Bonzini (**self).fmt(f) 821*c596199fSPaolo Bonzini } 822*c596199fSPaolo Bonzini } 823