aboutsummaryrefslogtreecommitdiff
path: root/rust/common/src/opaque.rs
blob: c941fb45462d88b599944165814784531f610728 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// SPDX-License-Identifier: MIT

//! ## Opaque wrappers
//!
//! The cell types from the previous section are useful at the boundaries
//! of code that requires interior mutability.  When writing glue code that
//! interacts directly with C structs, however, it is useful to operate
//! at a lower level.
//!
//! C functions often violate Rust's fundamental assumptions about memory
//! safety by modifying memory even if it is shared.  Furthermore, C structs
//! often start their life uninitialized and may be populated lazily.
//!
//! For this reason, this module provides the [`Opaque<T>`] type to opt out
//! of Rust's usual guarantees about the wrapped type. Access to the wrapped
//! value is always through raw pointers, obtained via methods like
//! [`as_mut_ptr()`](Opaque::as_mut_ptr) and [`as_ptr()`](Opaque::as_ptr). These
//! pointers can then be passed to C functions or dereferenced; both actions
//! require `unsafe` blocks, making it clear where safety guarantees must be
//! manually verified. For example
//!
//! ```ignore
//! unsafe {
//!     let state = Opaque::<MyStruct>::uninit();
//!     qemu_struct_init(state.as_mut_ptr());
//! }
//! ```
//!
//! [`Opaque<T>`] will usually be wrapped one level further, so that
//! bridge methods can be added to the wrapper:
//!
//! ```ignore
//! pub struct MyStruct(Opaque<bindings::MyStruct>);
//!
//! impl MyStruct {
//!     fn new() -> Pin<Box<MyStruct>> {
//!         let result = Box::pin(unsafe { Opaque::uninit() });
//!         unsafe { qemu_struct_init(result.as_mut_ptr()) };
//!         result
//!     }
//! }
//! ```
//!
//! This pattern of wrapping bindgen-generated types in [`Opaque<T>`] provides
//! several advantages:
//!
//! * The choice of traits to be implemented is not limited by the
//!   bindgen-generated code.  For example, [`Drop`] can be added without
//!   disabling [`Copy`] on the underlying bindgen type
//!
//! * [`Send`] and [`Sync`] implementations can be controlled by the wrapper
//!   type rather than being automatically derived from the C struct's layout
//!
//! * Methods can be implemented in a separate crate from the bindgen-generated
//!   bindings
//!
//! * [`Debug`](std::fmt::Debug) and [`Display`](std::fmt::Display)
//!   implementations can be customized to be more readable than the raw C
//!   struct representation
//!
//! The [`Opaque<T>`] type does not include BQL validation; it is possible to
//! assert in the code that the right lock is taken, to use it together
//! with a custom lock guard type, or to let C code take the lock, as
//! appropriate.  It is also possible to use it with non-thread-safe
//! types, since by default (unlike [`BqlCell`] and [`BqlRefCell`]
//! it is neither `Sync` nor `Send`.
//!
//! While [`Opaque<T>`] is necessary for C interop, it should be used sparingly
//! and only at FFI boundaries. For QEMU-specific types that need interior
//! mutability, prefer [`BqlCell`] or [`BqlRefCell`].
//!
//! [`BqlCell`]: ../../bql/cell/struct.BqlCell.html
//! [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html
use std::{cell::UnsafeCell, fmt, marker::PhantomPinned, mem::MaybeUninit, ptr::NonNull};

/// Stores an opaque value that is shared with C code.
///
/// Often, C structs can changed when calling a C function even if they are
/// behind a shared Rust reference, or they can be initialized lazily and have
/// invalid bit patterns (e.g. `3` for a [`bool`]).  This goes against Rust's
/// strict aliasing rules, which normally prevent mutation through shared
/// references.
///
/// Wrapping the struct with `Opaque<T>` ensures that the Rust compiler does not
/// assume the usual constraints that Rust structs require, and allows using
/// shared references on the Rust side.
///
/// `Opaque<T>` is `#[repr(transparent)]`, so that it matches the memory layout
/// of `T`.
#[repr(transparent)]
pub struct Opaque<T> {
    value: UnsafeCell<MaybeUninit<T>>,
    // PhantomPinned also allows multiple references to the `Opaque<T>`, i.e.
    // one `&mut Opaque<T>` can coexist with a `&mut T` or any number of `&T`;
    // see https://docs.rs/pinned-aliasable/latest/pinned_aliasable/.
    _pin: PhantomPinned,
}

impl<T> Opaque<T> {
    /// Creates a new shared reference from a C pointer
    ///
    /// # Safety
    ///
    /// The pointer must be valid, though it need not point to a valid value.
    pub unsafe fn from_raw<'a>(ptr: *mut T) -> &'a Self {
        let ptr = NonNull::new(ptr).unwrap().cast::<Self>();
        // SAFETY: Self is a transparent wrapper over T
        unsafe { ptr.as_ref() }
    }

    /// Creates a new opaque object with uninitialized contents.
    ///
    /// # Safety
    ///
    /// Ultimately the pointer to the returned value will be dereferenced
    /// in another `unsafe` block, for example when passing it to a C function,
    /// but the functions containing the dereference are usually safe.  The
    /// value returned from `uninit()` must be initialized and pinned before
    /// calling them.
    pub const unsafe fn uninit() -> Self {
        Self {
            value: UnsafeCell::new(MaybeUninit::uninit()),
            _pin: PhantomPinned,
        }
    }

    /// Creates a new opaque object with zeroed contents.
    ///
    /// # Safety
    ///
    /// Ultimately the pointer to the returned value will be dereferenced
    /// in another `unsafe` block, for example when passing it to a C function,
    /// but the functions containing the dereference are usually safe.  The
    /// value returned from `uninit()` must be pinned (and possibly initialized)
    /// before calling them.
    pub const unsafe fn zeroed() -> Self {
        Self {
            value: UnsafeCell::new(MaybeUninit::zeroed()),
            _pin: PhantomPinned,
        }
    }

    /// Returns a raw mutable pointer to the opaque data.
    pub const fn as_mut_ptr(&self) -> *mut T {
        UnsafeCell::get(&self.value).cast()
    }

    /// Returns a raw pointer to the opaque data.
    pub const fn as_ptr(&self) -> *const T {
        self.as_mut_ptr().cast_const()
    }

    /// Returns a raw pointer to the opaque data that can be passed to a
    /// C function as `void *`.
    pub const fn as_void_ptr(&self) -> *mut std::ffi::c_void {
        UnsafeCell::get(&self.value).cast()
    }

    /// Converts a raw pointer to the wrapped type.
    pub const fn raw_get(slot: *mut Self) -> *mut T {
        // Compare with Linux's raw_get method, which goes through an UnsafeCell
        // because it takes a *const Self instead.
        slot.cast()
    }
}

impl<T> fmt::Debug for Opaque<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut name: String = "Opaque<".to_string();
        name += std::any::type_name::<T>();
        name += ">";
        f.debug_tuple(&name).field(&self.as_ptr()).finish()
    }
}

impl<T: Default> Opaque<T> {
    /// Creates a new opaque object with default contents.
    ///
    /// # Safety
    ///
    /// Ultimately the pointer to the returned value will be dereferenced
    /// in another `unsafe` block, for example when passing it to a C function,
    /// but the functions containing the dereference are usually safe.  The
    /// value returned from `uninit()` must be pinned before calling them.
    pub unsafe fn new() -> Self {
        Self {
            value: UnsafeCell::new(MaybeUninit::new(T::default())),
            _pin: PhantomPinned,
        }
    }
}

/// Annotates [`Self`] as a transparent wrapper for another type.
///
/// Usually defined via the [`crate::Wrapper`] derive macro.
///
/// # Examples
///
/// ```
/// # use std::mem::ManuallyDrop;
/// # use common::opaque::Wrapper;
/// #[repr(transparent)]
/// pub struct Example {
///     inner: ManuallyDrop<String>,
/// }
///
/// unsafe impl Wrapper for Example {
///     type Wrapped = String;
/// }
/// ```
///
/// # Safety
///
/// `Self` must be a `#[repr(transparent)]` wrapper for the `Wrapped` type,
/// whether directly or indirectly.
///
/// # Methods
///
/// By convention, types that implement Wrapper also implement the following
/// methods:
///
/// ```ignore
/// pub const unsafe fn from_raw<'a>(value: *mut Self::Wrapped) -> &'a Self;
/// pub const unsafe fn as_mut_ptr(&self) -> *mut Self::Wrapped;
/// pub const unsafe fn as_ptr(&self) -> *const Self::Wrapped;
/// pub const unsafe fn raw_get(slot: *mut Self) -> *const Self::Wrapped;
/// ```
///
/// They are not defined here to allow them to be `const`.
pub unsafe trait Wrapper {
    type Wrapped;
}

unsafe impl<T> Wrapper for Opaque<T> {
    type Wrapped = T;
}