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