Skip to main content

aligned_vmem/
reservation_full_parts.rs

1use crate::Reservation;
2
3/// The full components returned by [`Reservation::into_full_parts`].
4///
5/// This struct contains ALL six fields needed to reconstruct a `Reservation`
6/// via [`Reservation::from_raw_parts`], eliminating the risk of metadata loss
7/// during round-trip. Unlike [`ReservationParts`](crate::reservation_parts::ReservationParts), it preserves `base`, `len`,
8/// and `granted_huge` in addition to the underlying reservation metadata.
9///
10/// This is the lossless round-trip alternative to [`ReservationParts`](crate::reservation_parts::ReservationParts). Use it
11/// when you need to temporarily extract all reservation state for later
12/// reconstruction.
13///
14/// **This struct holds the ONLY information that can free the underlying OS
15/// reservation** (task #1213/L3) — it has no `Drop` impl (see the
16/// "IMPORTANT" note on [`Reservation::into_full_parts`] for the full
17/// explanation), so a plain `drop` of a `ReservationFullParts` — letting it
18/// go out of scope without ever calling
19/// [`into_reservation`](Self::into_reservation) (and then dropping the
20/// resulting [`Reservation`](crate::Reservation)) or manually releasing via
21/// [`release`](crate::api::release) — silently leaks the mapping.
22/// `#[must_use]` here catches an ACCIDENTALLY discarded ownership token
23/// (e.g. a call to
24/// [`Reservation::into_full_parts`](crate::Reservation::into_full_parts)
25/// whose result is never bound to anything) at compile time; it does not
26/// and cannot prevent a DELIBERATE leak (e.g. binding the result to `_` or
27/// storing it and then dropping it later without acting on it).
28#[must_use = "dropping `ReservationFullParts` leaks the reservation — call \
29              `into_reservation` and drop the resulting `Reservation`, or \
30              release the `reservation`/`reservation_len`/`align` fields \
31              manually via `release`"]
32#[non_exhaustive]
33#[derive(Debug, PartialEq, Eq)]
34pub struct ReservationFullParts {
35    /// The aligned usable start pointer (from [`Reservation::as_ptr`]).
36    pub base: *mut u8,
37    /// The usable span size in bytes (from [`Reservation::len`]).
38    pub len: usize,
39    /// The underlying OS reservation start (from [`Reservation::reservation_ptr`]).
40    pub reservation: *mut u8,
41    /// The length of the reservation in bytes (from [`Reservation::reservation_len`]).
42    pub reservation_len: usize,
43    /// The alignment requested at reservation time.
44    pub align: usize,
45    /// Whether the OS granted huge pages for this reservation (from [`Reservation::is_huge`]).
46    pub granted_huge: bool,
47}
48
49impl ReservationFullParts {
50    /// Construct a `ReservationFullParts` from its component fields.
51    ///
52    /// This is the inverse of [`Reservation::into_full_parts`]. All six fields
53    /// are required to reconstruct a complete `Reservation` with no metadata loss.
54    ///
55    /// No message-less `#[must_use]` on this function itself (task
56    /// #1213/L3): it returns `Self`, and the type now carries its own
57    /// `#[must_use]` with a leak-specific message — see
58    /// [`ReservationParts::new`](crate::reservation_parts::ReservationParts::new)
59    /// for the identical reasoning.
60    #[inline]
61    pub const fn new(
62        base: *mut u8,
63        len: usize,
64        reservation: *mut u8,
65        reservation_len: usize,
66        align: usize,
67        granted_huge: bool,
68    ) -> Self {
69        Self {
70            base,
71            len,
72            reservation,
73            reservation_len,
74            align,
75            granted_huge,
76        }
77    }
78
79    /// Reconstruct a `Reservation` from these parts.
80    ///
81    /// This is a convenience wrapper around [`Reservation::from_raw_parts`]
82    /// that forwards all six fields. The same safety requirements apply.
83    ///
84    /// # Safety
85    ///
86    /// All six fields must satisfy the same invariants as documented for
87    /// [`Reservation::from_raw_parts`]. See that function's `# Safety` section
88    /// for full details.
89    #[must_use]
90    pub unsafe fn into_reservation(self) -> Reservation {
91        // SAFETY: Delegated to the caller — same contract as `from_raw_parts`.
92        unsafe {
93            Reservation::from_raw_parts(
94                self.base,
95                self.len,
96                self.reservation,
97                self.reservation_len,
98                self.align,
99                self.granted_huge,
100            )
101        }
102    }
103}
104
105// SAFETY (Send): `base`/`reservation` describe the same exclusively-owned OS
106// reservation `Reservation` itself is `Send` for (see the identical argument
107// on `unsafe impl Send for Reservation` in `reservation.rs`, and on
108// `ReservationParts` in `reservation_parts.rs`) — moving a
109// `ReservationFullParts` to another thread moves ownership of every byte it
110// describes. Every operation that dereferences either pointer is already
111// `unsafe`. Deliberately NOT `Sync`, for the same reason `Reservation` and
112// `ReservationParts` withhold it (task #1257/OH13-F4).
113unsafe impl Send for ReservationFullParts {}