1 // SPDX-License-Identifier: MIT 2 // 3 // This file is based on library/core/src/cell.rs from 4 // Rust 1.82.0. 5 // 6 // Permission is hereby granted, free of charge, to any 7 // person obtaining a copy of this software and associated 8 // documentation files (the "Software"), to deal in the 9 // Software without restriction, including without 10 // limitation the rights to use, copy, modify, merge, 11 // publish, distribute, sublicense, and/or sell copies of 12 // the Software, and to permit persons to whom the Software 13 // is furnished to do so, subject to the following 14 // conditions: 15 // 16 // The above copyright notice and this permission notice 17 // shall be included in all copies or substantial portions 18 // of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 // DEALINGS IN THE SOFTWARE. 29 30 //! BQL-protected mutable containers. 31 //! 32 //! Rust memory safety is based on this rule: Given an object `T`, it is only 33 //! possible to have one of the following: 34 //! 35 //! - Having several immutable references (`&T`) to the object (also known as 36 //! **aliasing**). 37 //! - Having one mutable reference (`&mut T`) to the object (also known as 38 //! **mutability**). 39 //! 40 //! This is enforced by the Rust compiler. However, there are situations where 41 //! this rule is not flexible enough. Sometimes it is required to have multiple 42 //! references to an object and yet mutate it. In particular, QEMU objects 43 //! usually have their pointer shared with the "outside world very early in 44 //! their lifetime", for example when they create their 45 //! [`MemoryRegion`s](crate::bindings::MemoryRegion). Therefore, individual 46 //! parts of a device must be made mutable in a controlled manner through the 47 //! use of cell types. 48 //! 49 //! This module provides a way to do so via the Big QEMU Lock. While 50 //! [`BqlCell<T>`] is essentially the same single-threaded primitive that is 51 //! available in `std::cell`, the BQL allows it to be used from a multi-threaded 52 //! context and to share references across threads, while maintaining Rust's 53 //! safety guarantees. For this reason, unlike its `std::cell` counterpart, 54 //! `BqlCell` implements the `Sync` trait. 55 //! 56 //! BQL checks are performed in debug builds but can be optimized away in 57 //! release builds, providing runtime safety during development with no overhead 58 //! in production. 59 //! 60 //! Warning: While `BqlCell` is similar to its `std::cell` counterpart, the two 61 //! are not interchangeable. Using `std::cell` types in QEMU device 62 //! implementations is usually incorrect and can lead to thread-safety issues. 63 //! 64 //! ## `BqlCell<T>` 65 //! 66 //! [`BqlCell<T>`] implements interior mutability by moving values in and out of 67 //! the cell. That is, an `&mut T` to the inner value can never be obtained as 68 //! long as the cell is shared. The value itself cannot be directly obtained 69 //! without copying it, cloning it, or replacing it with something else. This 70 //! type provides the following methods, all of which can be called only while 71 //! the BQL is held: 72 //! 73 //! - For types that implement [`Copy`], the [`get`](BqlCell::get) method 74 //! retrieves the current interior value by duplicating it. 75 //! - For types that implement [`Default`], the [`take`](BqlCell::take) method 76 //! replaces the current interior value with [`Default::default()`] and 77 //! returns the replaced value. 78 //! - All types have: 79 //! - [`replace`](BqlCell::replace): replaces the current interior value and 80 //! returns the replaced value. 81 //! - [`set`](BqlCell::set): this method replaces the interior value, 82 //! dropping the replaced value. 83 84 use std::{cell::UnsafeCell, cmp::Ordering, fmt, mem}; 85 86 use crate::bindings; 87 88 // TODO: When building doctests do not include the actual BQL, because cargo 89 // does not know how to link them to libqemuutil. This can be fixed by 90 // running rustdoc from "meson test" instead of relying on cargo. 91 pub fn bql_locked() -> bool { 92 // SAFETY: the function does nothing but return a thread-local bool 93 !cfg!(MESON) || unsafe { bindings::bql_locked() } 94 } 95 96 /// A mutable memory location that is protected by the Big QEMU Lock. 97 /// 98 /// # Memory layout 99 /// 100 /// `BqlCell<T>` has the same in-memory representation as its inner type `T`. 101 #[repr(transparent)] 102 pub struct BqlCell<T> { 103 value: UnsafeCell<T>, 104 } 105 106 // SAFETY: Same as for std::sync::Mutex. In the end this *is* a Mutex, 107 // except it is stored out-of-line 108 unsafe impl<T: Send> Send for BqlCell<T> {} 109 unsafe impl<T: Send> Sync for BqlCell<T> {} 110 111 impl<T: Copy> Clone for BqlCell<T> { 112 #[inline] 113 fn clone(&self) -> BqlCell<T> { 114 BqlCell::new(self.get()) 115 } 116 } 117 118 impl<T: Default> Default for BqlCell<T> { 119 /// Creates a `BqlCell<T>`, with the `Default` value for T. 120 #[inline] 121 fn default() -> BqlCell<T> { 122 BqlCell::new(Default::default()) 123 } 124 } 125 126 impl<T: PartialEq + Copy> PartialEq for BqlCell<T> { 127 #[inline] 128 fn eq(&self, other: &BqlCell<T>) -> bool { 129 self.get() == other.get() 130 } 131 } 132 133 impl<T: Eq + Copy> Eq for BqlCell<T> {} 134 135 impl<T: PartialOrd + Copy> PartialOrd for BqlCell<T> { 136 #[inline] 137 fn partial_cmp(&self, other: &BqlCell<T>) -> Option<Ordering> { 138 self.get().partial_cmp(&other.get()) 139 } 140 } 141 142 impl<T: Ord + Copy> Ord for BqlCell<T> { 143 #[inline] 144 fn cmp(&self, other: &BqlCell<T>) -> Ordering { 145 self.get().cmp(&other.get()) 146 } 147 } 148 149 impl<T> From<T> for BqlCell<T> { 150 /// Creates a new `BqlCell<T>` containing the given value. 151 fn from(t: T) -> BqlCell<T> { 152 BqlCell::new(t) 153 } 154 } 155 156 impl<T: fmt::Debug + Copy> fmt::Debug for BqlCell<T> { 157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 158 self.get().fmt(f) 159 } 160 } 161 162 impl<T: fmt::Display + Copy> fmt::Display for BqlCell<T> { 163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 164 self.get().fmt(f) 165 } 166 } 167 168 impl<T> BqlCell<T> { 169 /// Creates a new `BqlCell` containing the given value. 170 /// 171 /// # Examples 172 /// 173 /// ``` 174 /// use qemu_api::cell::BqlCell; 175 /// 176 /// let c = BqlCell::new(5); 177 /// ``` 178 #[inline] 179 pub const fn new(value: T) -> BqlCell<T> { 180 BqlCell { 181 value: UnsafeCell::new(value), 182 } 183 } 184 185 /// Sets the contained value. 186 /// 187 /// # Examples 188 /// 189 /// ``` 190 /// use qemu_api::cell::BqlCell; 191 /// 192 /// let c = BqlCell::new(5); 193 /// 194 /// c.set(10); 195 /// ``` 196 #[inline] 197 pub fn set(&self, val: T) { 198 self.replace(val); 199 } 200 201 /// Replaces the contained value with `val`, and returns the old contained 202 /// value. 203 /// 204 /// # Examples 205 /// 206 /// ``` 207 /// use qemu_api::cell::BqlCell; 208 /// 209 /// let cell = BqlCell::new(5); 210 /// assert_eq!(cell.get(), 5); 211 /// assert_eq!(cell.replace(10), 5); 212 /// assert_eq!(cell.get(), 10); 213 /// ``` 214 #[inline] 215 pub fn replace(&self, val: T) -> T { 216 assert!(bql_locked()); 217 // SAFETY: This can cause data races if called from multiple threads, 218 // but it won't happen as long as C code accesses the value 219 // under BQL protection only. 220 mem::replace(unsafe { &mut *self.value.get() }, val) 221 } 222 223 /// Unwraps the value, consuming the cell. 224 /// 225 /// # Examples 226 /// 227 /// ``` 228 /// use qemu_api::cell::BqlCell; 229 /// 230 /// let c = BqlCell::new(5); 231 /// let five = c.into_inner(); 232 /// 233 /// assert_eq!(five, 5); 234 /// ``` 235 pub fn into_inner(self) -> T { 236 assert!(bql_locked()); 237 self.value.into_inner() 238 } 239 } 240 241 impl<T: Copy> BqlCell<T> { 242 /// Returns a copy of the contained value. 243 /// 244 /// # Examples 245 /// 246 /// ``` 247 /// use qemu_api::cell::BqlCell; 248 /// 249 /// let c = BqlCell::new(5); 250 /// 251 /// let five = c.get(); 252 /// ``` 253 #[inline] 254 pub fn get(&self) -> T { 255 assert!(bql_locked()); 256 // SAFETY: This can cause data races if called from multiple threads, 257 // but it won't happen as long as C code accesses the value 258 // under BQL protection only. 259 unsafe { *self.value.get() } 260 } 261 } 262 263 impl<T> BqlCell<T> { 264 /// Returns a raw pointer to the underlying data in this cell. 265 /// 266 /// # Examples 267 /// 268 /// ``` 269 /// use qemu_api::cell::BqlCell; 270 /// 271 /// let c = BqlCell::new(5); 272 /// 273 /// let ptr = c.as_ptr(); 274 /// ``` 275 #[inline] 276 pub const fn as_ptr(&self) -> *mut T { 277 self.value.get() 278 } 279 } 280 281 impl<T: Default> BqlCell<T> { 282 /// Takes the value of the cell, leaving `Default::default()` in its place. 283 /// 284 /// # Examples 285 /// 286 /// ``` 287 /// use qemu_api::cell::BqlCell; 288 /// 289 /// let c = BqlCell::new(5); 290 /// let five = c.take(); 291 /// 292 /// assert_eq!(five, 5); 293 /// assert_eq!(c.into_inner(), 0); 294 /// ``` 295 pub fn take(&self) -> T { 296 self.replace(Default::default()) 297 } 298 } 299