xref: /qemu/rust/qemu-api/src/cell.rs (revision 8e194c0ea5cdbae05b77125a582f9927678121ee)
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