master
rs 236 lines 8.35 KB
Raw
1 // SPDX-License-Identifier: MIT
2
3 //! ## Opaque wrappers
4 //!
5 //! The cell types from the previous section are useful at the boundaries
6 //! of code that requires interior mutability. When writing glue code that
7 //! interacts directly with C structs, however, it is useful to operate
8 //! at a lower level.
9 //!
10 //! C functions often violate Rust's fundamental assumptions about memory
11 //! safety by modifying memory even if it is shared. Furthermore, C structs
12 //! often start their life uninitialized and may be populated lazily.
13 //!
14 //! For this reason, this module provides the [`Opaque<T>`] type to opt out
15 //! of Rust's usual guarantees about the wrapped type. Access to the wrapped
16 //! value is always through raw pointers, obtained via methods like
17 //! [`as_mut_ptr()`](Opaque::as_mut_ptr) and [`as_ptr()`](Opaque::as_ptr). These
18 //! pointers can then be passed to C functions or dereferenced; both actions
19 //! require `unsafe` blocks, making it clear where safety guarantees must be
20 //! manually verified. For example
21 //!
22 //! ```ignore
23 //! unsafe {
24 //! let state = Opaque::<MyStruct>::uninit();
25 //! qemu_struct_init(state.as_mut_ptr());
26 //! }
27 //! ```
28 //!
29 //! [`Opaque<T>`] will usually be wrapped one level further, so that
30 //! bridge methods can be added to the wrapper:
31 //!
32 //! ```ignore
33 //! pub struct MyStruct(Opaque<bindings::MyStruct>);
34 //!
35 //! impl MyStruct {
36 //! fn new() -> Pin<Box<MyStruct>> {
37 //! let result = Box::pin(unsafe { Opaque::uninit() });
38 //! unsafe { qemu_struct_init(result.as_mut_ptr()) };
39 //! result
40 //! }
41 //! }
42 //! ```
43 //!
44 //! This pattern of wrapping bindgen-generated types in [`Opaque<T>`] provides
45 //! several advantages:
46 //!
47 //! * The choice of traits to be implemented is not limited by the
48 //! bindgen-generated code. For example, [`Drop`] can be added without
49 //! disabling [`Copy`] on the underlying bindgen type
50 //!
51 //! * [`Send`] and [`Sync`] implementations can be controlled by the wrapper
52 //! type rather than being automatically derived from the C struct's layout
53 //!
54 //! * Methods can be implemented in a separate crate from the bindgen-generated
55 //! bindings
56 //!
57 //! * [`Debug`](std::fmt::Debug) and [`Display`](std::fmt::Display)
58 //! implementations can be customized to be more readable than the raw C
59 //! struct representation
60 //!
61 //! The [`Opaque<T>`] type does not include BQL validation; it is possible to
62 //! assert in the code that the right lock is taken, to use it together
63 //! with a custom lock guard type, or to let C code take the lock, as
64 //! appropriate. It is also possible to use it with non-thread-safe
65 //! types, since by default (unlike [`BqlCell`] and [`BqlRefCell`]
66 //! it is neither `Sync` nor `Send`.
67 //!
68 //! While [`Opaque<T>`] is necessary for C interop, it should be used sparingly
69 //! and only at FFI boundaries. For QEMU-specific types that need interior
70 //! mutability, prefer [`BqlCell`] or [`BqlRefCell`].
71 //!
72 //! [`BqlCell`]: ../../bql/cell/struct.BqlCell.html
73 //! [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html
74 use std::{cell::UnsafeCell, fmt, marker::PhantomPinned, mem::MaybeUninit, ptr::NonNull};
75
76 /// Stores an opaque value that is shared with C code.
77 ///
78 /// Often, C structs can changed when calling a C function even if they are
79 /// behind a shared Rust reference, or they can be initialized lazily and have
80 /// invalid bit patterns (e.g. `3` for a [`bool`]). This goes against Rust's
81 /// strict aliasing rules, which normally prevent mutation through shared
82 /// references.
83 ///
84 /// Wrapping the struct with `Opaque<T>` ensures that the Rust compiler does not
85 /// assume the usual constraints that Rust structs require, and allows using
86 /// shared references on the Rust side.
87 ///
88 /// `Opaque<T>` is `#[repr(transparent)]`, so that it matches the memory layout
89 /// of `T`.
90 #[repr(transparent)]
91 pub struct Opaque<T> {
92 value: UnsafeCell<MaybeUninit<T>>,
93 // PhantomPinned also allows multiple references to the `Opaque<T>`, i.e.
94 // one `&mut Opaque<T>` can coexist with a `&mut T` or any number of `&T`;
95 // see https://docs.rs/pinned-aliasable/latest/pinned_aliasable/.
96 _pin: PhantomPinned,
97 }
98
99 impl<T> Opaque<T> {
100 /// Creates a new shared reference from a C pointer
101 ///
102 /// # Safety
103 ///
104 /// The pointer must be valid, though it need not point to a valid value.
105 pub unsafe fn from_raw<'a>(ptr: *mut T) -> &'a Self {
106 let ptr = NonNull::new(ptr).unwrap().cast::<Self>();
107 // SAFETY: Self is a transparent wrapper over T
108 unsafe { ptr.as_ref() }
109 }
110
111 /// Creates a new opaque object with uninitialized contents.
112 ///
113 /// # Safety
114 ///
115 /// Ultimately the pointer to the returned value will be dereferenced
116 /// in another `unsafe` block, for example when passing it to a C function,
117 /// but the functions containing the dereference are usually safe. The
118 /// value returned from `uninit()` must be initialized and pinned before
119 /// calling them.
120 pub const unsafe fn uninit() -> Self {
121 Self {
122 value: UnsafeCell::new(MaybeUninit::uninit()),
123 _pin: PhantomPinned,
124 }
125 }
126
127 /// Creates a new opaque object with zeroed contents.
128 ///
129 /// # Safety
130 ///
131 /// Ultimately the pointer to the returned value will be dereferenced
132 /// in another `unsafe` block, for example when passing it to a C function,
133 /// but the functions containing the dereference are usually safe. The
134 /// value returned from `uninit()` must be pinned (and possibly initialized)
135 /// before calling them.
136 pub const unsafe fn zeroed() -> Self {
137 Self {
138 value: UnsafeCell::new(MaybeUninit::zeroed()),
139 _pin: PhantomPinned,
140 }
141 }
142
143 /// Returns a raw mutable pointer to the opaque data.
144 pub const fn as_mut_ptr(&self) -> *mut T {
145 UnsafeCell::get(&self.value).cast()
146 }
147
148 /// Returns a raw pointer to the opaque data.
149 pub const fn as_ptr(&self) -> *const T {
150 self.as_mut_ptr().cast_const()
151 }
152
153 /// Returns a raw pointer to the opaque data that can be passed to a
154 /// C function as `void *`.
155 pub const fn as_void_ptr(&self) -> *mut std::ffi::c_void {
156 UnsafeCell::get(&self.value).cast()
157 }
158
159 /// Converts a raw pointer to the wrapped type.
160 pub const fn raw_get(slot: *mut Self) -> *mut T {
161 // Compare with Linux's raw_get method, which goes through an UnsafeCell
162 // because it takes a *const Self instead.
163 slot.cast()
164 }
165 }
166
167 impl<T> fmt::Debug for Opaque<T> {
168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 let mut name: String = "Opaque<".to_string();
170 name += std::any::type_name::<T>();
171 name += ">";
172 f.debug_tuple(&name).field(&self.as_ptr()).finish()
173 }
174 }
175
176 impl<T: Default> Opaque<T> {
177 /// Creates a new opaque object with default contents.
178 ///
179 /// # Safety
180 ///
181 /// Ultimately the pointer to the returned value will be dereferenced
182 /// in another `unsafe` block, for example when passing it to a C function,
183 /// but the functions containing the dereference are usually safe. The
184 /// value returned from `uninit()` must be pinned before calling them.
185 pub unsafe fn new() -> Self {
186 Self {
187 value: UnsafeCell::new(MaybeUninit::new(T::default())),
188 _pin: PhantomPinned,
189 }
190 }
191 }
192
193 /// Annotates [`Self`] as a transparent wrapper for another type.
194 ///
195 /// Usually defined via the [`crate::Wrapper`] derive macro.
196 ///
197 /// # Examples
198 ///
199 /// ```
200 /// # use std::mem::ManuallyDrop;
201 /// # use common::opaque::Wrapper;
202 /// #[repr(transparent)]
203 /// pub struct Example {
204 /// inner: ManuallyDrop<String>,
205 /// }
206 ///
207 /// unsafe impl Wrapper for Example {
208 /// type Wrapped = String;
209 /// }
210 /// ```
211 ///
212 /// # Safety
213 ///
214 /// `Self` must be a `#[repr(transparent)]` wrapper for the `Wrapped` type,
215 /// whether directly or indirectly.
216 ///
217 /// # Methods
218 ///
219 /// By convention, types that implement Wrapper also implement the following
220 /// methods:
221 ///
222 /// ```ignore
223 /// pub const unsafe fn from_raw<'a>(value: *mut Self::Wrapped) -> &'a Self;
224 /// pub const unsafe fn as_mut_ptr(&self) -> *mut Self::Wrapped;
225 /// pub const unsafe fn as_ptr(&self) -> *const Self::Wrapped;
226 /// pub const unsafe fn raw_get(slot: *mut Self) -> *const Self::Wrapped;
227 /// ```
228 ///
229 /// They are not defined here to allow them to be `const`.
230 pub unsafe trait Wrapper {
231 type Wrapped;
232 }
233
234 unsafe impl<T> Wrapper for Opaque<T> {
235 type Wrapped = T;
236 }