1*be431cd8SAndroid Build Coastguard Worker //! libfmq Rust wrapper
2*be431cd8SAndroid Build Coastguard Worker
3*be431cd8SAndroid Build Coastguard Worker /*
4*be431cd8SAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
5*be431cd8SAndroid Build Coastguard Worker *
6*be431cd8SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
7*be431cd8SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
8*be431cd8SAndroid Build Coastguard Worker * You may obtain a copy of the License at
9*be431cd8SAndroid Build Coastguard Worker *
10*be431cd8SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
11*be431cd8SAndroid Build Coastguard Worker *
12*be431cd8SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
13*be431cd8SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
14*be431cd8SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*be431cd8SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
16*be431cd8SAndroid Build Coastguard Worker * limitations under the License.
17*be431cd8SAndroid Build Coastguard Worker */
18*be431cd8SAndroid Build Coastguard Worker
19*be431cd8SAndroid Build Coastguard Worker use fmq_bindgen::{
20*be431cd8SAndroid Build Coastguard Worker convertDesc, convertGrantor, descFlags, descGrantors, descHandleFDs, descHandleInts,
21*be431cd8SAndroid Build Coastguard Worker descHandleNumFDs, descHandleNumInts, descNumGrantors, descQuantum, freeDesc,
22*be431cd8SAndroid Build Coastguard Worker ndk_ScopedFileDescriptor, ErasedMessageQueue, ErasedMessageQueueDesc, GrantorDescriptor,
23*be431cd8SAndroid Build Coastguard Worker MQDescriptor, MemTransaction, NativeHandle, ParcelFileDescriptor, SynchronizedReadWrite,
24*be431cd8SAndroid Build Coastguard Worker };
25*be431cd8SAndroid Build Coastguard Worker
26*be431cd8SAndroid Build Coastguard Worker use std::ptr::addr_of_mut;
27*be431cd8SAndroid Build Coastguard Worker
28*be431cd8SAndroid Build Coastguard Worker use log::error;
29*be431cd8SAndroid Build Coastguard Worker
30*be431cd8SAndroid Build Coastguard Worker /// A trait indicating that a type is safe to pass through shared memory.
31*be431cd8SAndroid Build Coastguard Worker ///
32*be431cd8SAndroid Build Coastguard Worker /// # Safety
33*be431cd8SAndroid Build Coastguard Worker ///
34*be431cd8SAndroid Build Coastguard Worker /// This requires that the type must not contain any capabilities such as file
35*be431cd8SAndroid Build Coastguard Worker /// descriptors or heap allocations, and that it must be permitted to access
36*be431cd8SAndroid Build Coastguard Worker /// all bytes of its representation (so it must not contain any padding bytes).
37*be431cd8SAndroid Build Coastguard Worker ///
38*be431cd8SAndroid Build Coastguard Worker /// Because being stored in shared memory the allows the type to be accessed
39*be431cd8SAndroid Build Coastguard Worker /// from different processes, it may also be accessed from different threads in
40*be431cd8SAndroid Build Coastguard Worker /// the same process. As such, `Share` is a supertrait of `Sync`.
41*be431cd8SAndroid Build Coastguard Worker pub unsafe trait Share: Sync {}
42*be431cd8SAndroid Build Coastguard Worker
43*be431cd8SAndroid Build Coastguard Worker // SAFETY: All types implementing the `zerocopy::AsBytes` trait implement `Share`.
44*be431cd8SAndroid Build Coastguard Worker unsafe impl<T: zerocopy::AsBytes + zerocopy::FromBytes + Send + Sync> Share for T {}
45*be431cd8SAndroid Build Coastguard Worker
46*be431cd8SAndroid Build Coastguard Worker /// An IPC message queue for values of type T.
47*be431cd8SAndroid Build Coastguard Worker pub struct MessageQueue<T> {
48*be431cd8SAndroid Build Coastguard Worker inner: ErasedMessageQueue,
49*be431cd8SAndroid Build Coastguard Worker ty: core::marker::PhantomData<T>,
50*be431cd8SAndroid Build Coastguard Worker }
51*be431cd8SAndroid Build Coastguard Worker
52*be431cd8SAndroid Build Coastguard Worker /** A write completion from the MessageQueue::write() method.
53*be431cd8SAndroid Build Coastguard Worker
54*be431cd8SAndroid Build Coastguard Worker This completion mutably borrows the MessageQueue to prevent concurrent writes;
55*be431cd8SAndroid Build Coastguard Worker these must be forbidden because the underlying AidlMessageQueue only stores the
56*be431cd8SAndroid Build Coastguard Worker number of outstanding writes, not which have and have not completed, so they
57*be431cd8SAndroid Build Coastguard Worker must complete in order. */
58*be431cd8SAndroid Build Coastguard Worker #[must_use]
59*be431cd8SAndroid Build Coastguard Worker pub struct WriteCompletion<'a, T: Share> {
60*be431cd8SAndroid Build Coastguard Worker inner: MemTransaction,
61*be431cd8SAndroid Build Coastguard Worker queue: &'a mut MessageQueue<T>,
62*be431cd8SAndroid Build Coastguard Worker n_elems: usize,
63*be431cd8SAndroid Build Coastguard Worker n_written: usize,
64*be431cd8SAndroid Build Coastguard Worker }
65*be431cd8SAndroid Build Coastguard Worker
66*be431cd8SAndroid Build Coastguard Worker impl<'a, T: Share> WriteCompletion<'a, T> {
67*be431cd8SAndroid Build Coastguard Worker /// Obtain a pointer to the location at which the idx'th item should be
68*be431cd8SAndroid Build Coastguard Worker /// stored.
69*be431cd8SAndroid Build Coastguard Worker ///
70*be431cd8SAndroid Build Coastguard Worker /// The returned pointer is only valid while `self` has not been dropped and
71*be431cd8SAndroid Build Coastguard Worker /// is invalidated by any call to `self.write`. The pointer should be used
72*be431cd8SAndroid Build Coastguard Worker /// with `std::ptr::write` or a DMA API to initialize the underlying storage
73*be431cd8SAndroid Build Coastguard Worker /// before calling `assume_written` to indicate how many elements were
74*be431cd8SAndroid Build Coastguard Worker /// written.
75*be431cd8SAndroid Build Coastguard Worker ///
76*be431cd8SAndroid Build Coastguard Worker /// It is only permitted to access at most `contiguous_count(idx)` items
77*be431cd8SAndroid Build Coastguard Worker /// via offsets from the returned address.
78*be431cd8SAndroid Build Coastguard Worker ///
79*be431cd8SAndroid Build Coastguard Worker /// Calling this method with a greater `idx` may return a pointer to another
80*be431cd8SAndroid Build Coastguard Worker /// memory region of different size than the first.
ptr(&self, idx: usize) -> *mut T81*be431cd8SAndroid Build Coastguard Worker pub fn ptr(&self, idx: usize) -> *mut T {
82*be431cd8SAndroid Build Coastguard Worker if idx >= self.n_elems {
83*be431cd8SAndroid Build Coastguard Worker panic!(
84*be431cd8SAndroid Build Coastguard Worker "indexing out of bound: ReadCompletion for {} elements but idx {} accessed",
85*be431cd8SAndroid Build Coastguard Worker self.n_elems, idx
86*be431cd8SAndroid Build Coastguard Worker )
87*be431cd8SAndroid Build Coastguard Worker }
88*be431cd8SAndroid Build Coastguard Worker ptr(&self.inner, idx)
89*be431cd8SAndroid Build Coastguard Worker }
90*be431cd8SAndroid Build Coastguard Worker
91*be431cd8SAndroid Build Coastguard Worker /// Return the number of contiguous elements that may be stored starting at
92*be431cd8SAndroid Build Coastguard Worker /// the given index in the backing buffer corresponding to the given index.
93*be431cd8SAndroid Build Coastguard Worker ///
94*be431cd8SAndroid Build Coastguard Worker /// Intended for use with the `ptr` method.
95*be431cd8SAndroid Build Coastguard Worker ///
96*be431cd8SAndroid Build Coastguard Worker /// Returns 0 if `idx` is greater than or equal to the completion's element
97*be431cd8SAndroid Build Coastguard Worker /// count.
contiguous_count(&self, idx: usize) -> usize98*be431cd8SAndroid Build Coastguard Worker pub fn contiguous_count(&self, idx: usize) -> usize {
99*be431cd8SAndroid Build Coastguard Worker contiguous_count(&self.inner, idx, self.n_elems)
100*be431cd8SAndroid Build Coastguard Worker }
101*be431cd8SAndroid Build Coastguard Worker
102*be431cd8SAndroid Build Coastguard Worker /// Returns how many elements still must be written to this WriteCompletion
103*be431cd8SAndroid Build Coastguard Worker /// before dropping it.
required_elements(&self) -> usize104*be431cd8SAndroid Build Coastguard Worker pub fn required_elements(&self) -> usize {
105*be431cd8SAndroid Build Coastguard Worker assert!(self.n_written <= self.n_elems);
106*be431cd8SAndroid Build Coastguard Worker self.n_elems - self.n_written
107*be431cd8SAndroid Build Coastguard Worker }
108*be431cd8SAndroid Build Coastguard Worker
109*be431cd8SAndroid Build Coastguard Worker /// Write one item to `self`. Fails and returns the item if `self` is full.
write(&mut self, data: T) -> Result<(), T>110*be431cd8SAndroid Build Coastguard Worker pub fn write(&mut self, data: T) -> Result<(), T> {
111*be431cd8SAndroid Build Coastguard Worker if self.required_elements() > 0 {
112*be431cd8SAndroid Build Coastguard Worker // SAFETY: `self.ptr(self.n_written)` is known to be uninitialized.
113*be431cd8SAndroid Build Coastguard Worker // The dtor of data, if any, will not run because `data` is moved
114*be431cd8SAndroid Build Coastguard Worker // out of here.
115*be431cd8SAndroid Build Coastguard Worker unsafe { self.ptr(self.n_written).write(data) };
116*be431cd8SAndroid Build Coastguard Worker self.n_written += 1;
117*be431cd8SAndroid Build Coastguard Worker Ok(())
118*be431cd8SAndroid Build Coastguard Worker } else {
119*be431cd8SAndroid Build Coastguard Worker Err(data)
120*be431cd8SAndroid Build Coastguard Worker }
121*be431cd8SAndroid Build Coastguard Worker }
122*be431cd8SAndroid Build Coastguard Worker
123*be431cd8SAndroid Build Coastguard Worker /// Promise to the `WriteCompletion` that `n_newly_written` elements have
124*be431cd8SAndroid Build Coastguard Worker /// been written with unsafe code or DMA to the pointer returned by the
125*be431cd8SAndroid Build Coastguard Worker /// `ptr` method.
126*be431cd8SAndroid Build Coastguard Worker ///
127*be431cd8SAndroid Build Coastguard Worker /// Panics if `n_newly_written` exceeds the number of elements yet required.
128*be431cd8SAndroid Build Coastguard Worker ///
129*be431cd8SAndroid Build Coastguard Worker /// # Safety
130*be431cd8SAndroid Build Coastguard Worker /// It is UB to call this method except after calling the `ptr` method and
131*be431cd8SAndroid Build Coastguard Worker /// writing the specified number of values of type T to that location.
assume_written(&mut self, n_newly_written: usize)132*be431cd8SAndroid Build Coastguard Worker pub unsafe fn assume_written(&mut self, n_newly_written: usize) {
133*be431cd8SAndroid Build Coastguard Worker assert!(n_newly_written < self.required_elements());
134*be431cd8SAndroid Build Coastguard Worker self.n_written += n_newly_written;
135*be431cd8SAndroid Build Coastguard Worker }
136*be431cd8SAndroid Build Coastguard Worker }
137*be431cd8SAndroid Build Coastguard Worker
138*be431cd8SAndroid Build Coastguard Worker impl<'a, T: Share> Drop for WriteCompletion<'a, T> {
drop(&mut self)139*be431cd8SAndroid Build Coastguard Worker fn drop(&mut self) {
140*be431cd8SAndroid Build Coastguard Worker if self.n_written < self.n_elems {
141*be431cd8SAndroid Build Coastguard Worker error!(
142*be431cd8SAndroid Build Coastguard Worker "WriteCompletion dropped without writing to all elements ({}/{} written)",
143*be431cd8SAndroid Build Coastguard Worker self.n_written, self.n_elems
144*be431cd8SAndroid Build Coastguard Worker );
145*be431cd8SAndroid Build Coastguard Worker }
146*be431cd8SAndroid Build Coastguard Worker let txn = std::mem::take(&mut self.inner);
147*be431cd8SAndroid Build Coastguard Worker self.queue.commit_write(txn);
148*be431cd8SAndroid Build Coastguard Worker }
149*be431cd8SAndroid Build Coastguard Worker }
150*be431cd8SAndroid Build Coastguard Worker
151*be431cd8SAndroid Build Coastguard Worker impl<T: Share> MessageQueue<T> {
type_size() -> usize152*be431cd8SAndroid Build Coastguard Worker const fn type_size() -> usize {
153*be431cd8SAndroid Build Coastguard Worker std::mem::size_of::<T>()
154*be431cd8SAndroid Build Coastguard Worker }
155*be431cd8SAndroid Build Coastguard Worker
156*be431cd8SAndroid Build Coastguard Worker /// Create a new MessageQueue with capacity for `elems` elements.
new(elems: usize, event_word: bool) -> Self157*be431cd8SAndroid Build Coastguard Worker pub fn new(elems: usize, event_word: bool) -> Self {
158*be431cd8SAndroid Build Coastguard Worker Self {
159*be431cd8SAndroid Build Coastguard Worker // SAFETY: Calling bindgen'd constructor. The only argument that
160*be431cd8SAndroid Build Coastguard Worker // can't be validated by the implementation is the quantum, which
161*be431cd8SAndroid Build Coastguard Worker // must equal the element size.
162*be431cd8SAndroid Build Coastguard Worker inner: unsafe { ErasedMessageQueue::new1(elems, event_word, Self::type_size()) },
163*be431cd8SAndroid Build Coastguard Worker ty: core::marker::PhantomData,
164*be431cd8SAndroid Build Coastguard Worker }
165*be431cd8SAndroid Build Coastguard Worker }
166*be431cd8SAndroid Build Coastguard Worker
167*be431cd8SAndroid Build Coastguard Worker /// Create a MessageQueue connected to another existing instance from its
168*be431cd8SAndroid Build Coastguard Worker /// descriptor.
from_desc(desc: &MQDescriptor<T, SynchronizedReadWrite>, reset_pointers: bool) -> Self169*be431cd8SAndroid Build Coastguard Worker pub fn from_desc(desc: &MQDescriptor<T, SynchronizedReadWrite>, reset_pointers: bool) -> Self {
170*be431cd8SAndroid Build Coastguard Worker let mut grantors = desc
171*be431cd8SAndroid Build Coastguard Worker .grantors
172*be431cd8SAndroid Build Coastguard Worker .iter()
173*be431cd8SAndroid Build Coastguard Worker // SAFETY: this just forwards the integers to the GrantorDescriptor
174*be431cd8SAndroid Build Coastguard Worker // constructor; GrantorDescriptor is POD.
175*be431cd8SAndroid Build Coastguard Worker .map(|g| unsafe { convertGrantor(g.fdIndex, g.offset, g.extent) })
176*be431cd8SAndroid Build Coastguard Worker .collect::<Vec<_>>();
177*be431cd8SAndroid Build Coastguard Worker
178*be431cd8SAndroid Build Coastguard Worker // SAFETY: These pointer/length pairs come from Vecs that will outlive
179*be431cd8SAndroid Build Coastguard Worker // this function call, and the call itself copies all data it needs out
180*be431cd8SAndroid Build Coastguard Worker // of them.
181*be431cd8SAndroid Build Coastguard Worker let cpp_desc = unsafe {
182*be431cd8SAndroid Build Coastguard Worker convertDesc(
183*be431cd8SAndroid Build Coastguard Worker grantors.as_mut_ptr(),
184*be431cd8SAndroid Build Coastguard Worker grantors.len(),
185*be431cd8SAndroid Build Coastguard Worker desc.handle.fds.as_ptr().cast(),
186*be431cd8SAndroid Build Coastguard Worker desc.handle.fds.len(),
187*be431cd8SAndroid Build Coastguard Worker desc.handle.ints.as_ptr(),
188*be431cd8SAndroid Build Coastguard Worker desc.handle.ints.len(),
189*be431cd8SAndroid Build Coastguard Worker desc.quantum,
190*be431cd8SAndroid Build Coastguard Worker desc.flags,
191*be431cd8SAndroid Build Coastguard Worker )
192*be431cd8SAndroid Build Coastguard Worker };
193*be431cd8SAndroid Build Coastguard Worker // SAFETY: Calling bindgen'd constructor which does not store cpp_desc,
194*be431cd8SAndroid Build Coastguard Worker // but just passes it to the initializer of AidlMQDescriptorShim, which
195*be431cd8SAndroid Build Coastguard Worker // deep-copies it.
196*be431cd8SAndroid Build Coastguard Worker let inner = unsafe { ErasedMessageQueue::new(cpp_desc, reset_pointers) };
197*be431cd8SAndroid Build Coastguard Worker // SAFETY: we must free the desc returned by convertDesc; the pointer
198*be431cd8SAndroid Build Coastguard Worker // was just returned above so we know it is valid.
199*be431cd8SAndroid Build Coastguard Worker unsafe { freeDesc(cpp_desc) };
200*be431cd8SAndroid Build Coastguard Worker Self { inner, ty: core::marker::PhantomData }
201*be431cd8SAndroid Build Coastguard Worker }
202*be431cd8SAndroid Build Coastguard Worker
203*be431cd8SAndroid Build Coastguard Worker /// Obtain a copy of the MessageQueue's descriptor, which may be used to
204*be431cd8SAndroid Build Coastguard Worker /// access it remotely.
dupe_desc(&self) -> MQDescriptor<T, SynchronizedReadWrite>205*be431cd8SAndroid Build Coastguard Worker pub fn dupe_desc(&self) -> MQDescriptor<T, SynchronizedReadWrite> {
206*be431cd8SAndroid Build Coastguard Worker // SAFETY: dupeDesc may be called on any valid ErasedMessageQueue; it
207*be431cd8SAndroid Build Coastguard Worker // simply forwards to dupeDesc on the inner AidlMessageQueue and wraps
208*be431cd8SAndroid Build Coastguard Worker // in a heap allocation.
209*be431cd8SAndroid Build Coastguard Worker let erased_desc: *mut ErasedMessageQueueDesc = unsafe { self.inner.dupeDesc() };
210*be431cd8SAndroid Build Coastguard Worker let grantor_to_rust =
211*be431cd8SAndroid Build Coastguard Worker |g: &fmq_bindgen::aidl_android_hardware_common_fmq_GrantorDescriptor| {
212*be431cd8SAndroid Build Coastguard Worker GrantorDescriptor { fdIndex: g.fdIndex, offset: g.offset, extent: g.extent }
213*be431cd8SAndroid Build Coastguard Worker };
214*be431cd8SAndroid Build Coastguard Worker
215*be431cd8SAndroid Build Coastguard Worker let scoped_to_parcel_fd = |fd: &ndk_ScopedFileDescriptor| {
216*be431cd8SAndroid Build Coastguard Worker use std::os::fd::{BorrowedFd, FromRawFd, OwnedFd};
217*be431cd8SAndroid Build Coastguard Worker // SAFETY: the fd is already open as an invariant of ndk::ScopedFileDescriptor, so
218*be431cd8SAndroid Build Coastguard Worker // it will not be -1, as required by BorrowedFd.
219*be431cd8SAndroid Build Coastguard Worker let borrowed = unsafe { BorrowedFd::borrow_raw(fd._base as i32) };
220*be431cd8SAndroid Build Coastguard Worker ParcelFileDescriptor::new(match borrowed.try_clone_to_owned() {
221*be431cd8SAndroid Build Coastguard Worker Ok(fd) => fd,
222*be431cd8SAndroid Build Coastguard Worker Err(e) => {
223*be431cd8SAndroid Build Coastguard Worker error!("could not dup NativeHandle fd {}: {}", fd._base, e);
224*be431cd8SAndroid Build Coastguard Worker // SAFETY: OwnedFd requires the fd is not -1. If we failed to dup the fd,
225*be431cd8SAndroid Build Coastguard Worker // other code downstream will fail, but we can do no better than pass it on.
226*be431cd8SAndroid Build Coastguard Worker unsafe { OwnedFd::from_raw_fd(fd._base as i32) }
227*be431cd8SAndroid Build Coastguard Worker }
228*be431cd8SAndroid Build Coastguard Worker })
229*be431cd8SAndroid Build Coastguard Worker };
230*be431cd8SAndroid Build Coastguard Worker
231*be431cd8SAndroid Build Coastguard Worker // First, we create a desc with the wrong type, because we cannot create one whole cloth of
232*be431cd8SAndroid Build Coastguard Worker // our desired return type unless T implements Default. This Default requirement is
233*be431cd8SAndroid Build Coastguard Worker // superfluous (T::default() is never called), so we then transmute to our desired type.
234*be431cd8SAndroid Build Coastguard Worker let desc = MQDescriptor::<(), SynchronizedReadWrite>::default();
235*be431cd8SAndroid Build Coastguard Worker // SAFETY: This transmute changes only the element type parameter of the MQDescriptor. The
236*be431cd8SAndroid Build Coastguard Worker // layout of an MQDescriptor does not depend on T as T appears in it only in PhantomData.
237*be431cd8SAndroid Build Coastguard Worker let mut desc: MQDescriptor<T, SynchronizedReadWrite> = unsafe { std::mem::transmute(desc) };
238*be431cd8SAndroid Build Coastguard Worker // SAFETY: These slices are created out of the pointer and length pairs exposed by the
239*be431cd8SAndroid Build Coastguard Worker // individual descFoo accessors, so we know they are valid pointer/lengths and point to
240*be431cd8SAndroid Build Coastguard Worker // data that will continue to exist as long as the desc does.
241*be431cd8SAndroid Build Coastguard Worker //
242*be431cd8SAndroid Build Coastguard Worker // Calls to the descFoo accessors on erased_desc are sound because we know inner.dupeDesc
243*be431cd8SAndroid Build Coastguard Worker // returns a valid pointer to a new heap-allocated ErasedMessageQueueDesc.
244*be431cd8SAndroid Build Coastguard Worker let (grantors, fds, ints, quantum, flags) = unsafe {
245*be431cd8SAndroid Build Coastguard Worker let grantors = slice_from_raw_parts_or_empty(
246*be431cd8SAndroid Build Coastguard Worker descGrantors(erased_desc),
247*be431cd8SAndroid Build Coastguard Worker descNumGrantors(erased_desc),
248*be431cd8SAndroid Build Coastguard Worker );
249*be431cd8SAndroid Build Coastguard Worker let fds = slice_from_raw_parts_or_empty(
250*be431cd8SAndroid Build Coastguard Worker descHandleFDs(erased_desc),
251*be431cd8SAndroid Build Coastguard Worker descHandleNumFDs(erased_desc),
252*be431cd8SAndroid Build Coastguard Worker );
253*be431cd8SAndroid Build Coastguard Worker let ints = slice_from_raw_parts_or_empty(
254*be431cd8SAndroid Build Coastguard Worker descHandleInts(erased_desc),
255*be431cd8SAndroid Build Coastguard Worker descHandleNumInts(erased_desc),
256*be431cd8SAndroid Build Coastguard Worker );
257*be431cd8SAndroid Build Coastguard Worker let quantum = descQuantum(erased_desc);
258*be431cd8SAndroid Build Coastguard Worker let flags = descFlags(erased_desc);
259*be431cd8SAndroid Build Coastguard Worker (grantors, fds, ints, quantum, flags)
260*be431cd8SAndroid Build Coastguard Worker };
261*be431cd8SAndroid Build Coastguard Worker let fds = fds.iter().map(scoped_to_parcel_fd).collect();
262*be431cd8SAndroid Build Coastguard Worker let ints = ints.to_vec();
263*be431cd8SAndroid Build Coastguard Worker desc.grantors = grantors.iter().map(grantor_to_rust).collect();
264*be431cd8SAndroid Build Coastguard Worker desc.handle = NativeHandle { fds, ints };
265*be431cd8SAndroid Build Coastguard Worker desc.quantum = quantum;
266*be431cd8SAndroid Build Coastguard Worker desc.flags = flags;
267*be431cd8SAndroid Build Coastguard Worker // SAFETY: we must free the desc returned by dupeDesc; the pointer was
268*be431cd8SAndroid Build Coastguard Worker // just returned above so we know it is valid.
269*be431cd8SAndroid Build Coastguard Worker unsafe { freeDesc(erased_desc) };
270*be431cd8SAndroid Build Coastguard Worker desc
271*be431cd8SAndroid Build Coastguard Worker }
272*be431cd8SAndroid Build Coastguard Worker
273*be431cd8SAndroid Build Coastguard Worker /// Begin a write transaction. The returned WriteCompletion can be used to
274*be431cd8SAndroid Build Coastguard Worker /// write into the region allocated for the transaction.
write(&mut self) -> Option<WriteCompletion<T>>275*be431cd8SAndroid Build Coastguard Worker pub fn write(&mut self) -> Option<WriteCompletion<T>> {
276*be431cd8SAndroid Build Coastguard Worker self.write_many(1)
277*be431cd8SAndroid Build Coastguard Worker }
278*be431cd8SAndroid Build Coastguard Worker
279*be431cd8SAndroid Build Coastguard Worker /// Begin a write transaction for multiple items. See `MessageQueue::write`.
write_many(&mut self, n: usize) -> Option<WriteCompletion<T>>280*be431cd8SAndroid Build Coastguard Worker pub fn write_many(&mut self, n: usize) -> Option<WriteCompletion<T>> {
281*be431cd8SAndroid Build Coastguard Worker let txn = self.begin_write(n)?;
282*be431cd8SAndroid Build Coastguard Worker Some(WriteCompletion { inner: txn, queue: self, n_elems: n, n_written: 0 })
283*be431cd8SAndroid Build Coastguard Worker }
284*be431cd8SAndroid Build Coastguard Worker
commit_write(&mut self, txn: MemTransaction) -> bool285*be431cd8SAndroid Build Coastguard Worker fn commit_write(&mut self, txn: MemTransaction) -> bool {
286*be431cd8SAndroid Build Coastguard Worker // SAFETY: simply calls commitWrite with the txn length. The txn must
287*be431cd8SAndroid Build Coastguard Worker // only use its first MemRegion.
288*be431cd8SAndroid Build Coastguard Worker unsafe { self.inner.commitWrite(txn.first.length + txn.second.length) }
289*be431cd8SAndroid Build Coastguard Worker }
290*be431cd8SAndroid Build Coastguard Worker
begin_write(&self, n: usize) -> Option<MemTransaction>291*be431cd8SAndroid Build Coastguard Worker fn begin_write(&self, n: usize) -> Option<MemTransaction> {
292*be431cd8SAndroid Build Coastguard Worker let mut txn: MemTransaction = Default::default();
293*be431cd8SAndroid Build Coastguard Worker // SAFETY: we pass a raw pointer to txn, which is used only during the
294*be431cd8SAndroid Build Coastguard Worker // call to beginWrite to write the txn's MemRegion fields, which are raw
295*be431cd8SAndroid Build Coastguard Worker // pointers and lengths pointing into the queue. The pointer to txn is
296*be431cd8SAndroid Build Coastguard Worker // not stored.
297*be431cd8SAndroid Build Coastguard Worker unsafe { self.inner.beginWrite(n, addr_of_mut!(txn)) }.then_some(txn)
298*be431cd8SAndroid Build Coastguard Worker }
299*be431cd8SAndroid Build Coastguard Worker }
300*be431cd8SAndroid Build Coastguard Worker
301*be431cd8SAndroid Build Coastguard Worker /// Forms a slice from a pointer and a length.
302*be431cd8SAndroid Build Coastguard Worker ///
303*be431cd8SAndroid Build Coastguard Worker /// Returns an empty slice when `data` is a null pointer and `len` is zero.
304*be431cd8SAndroid Build Coastguard Worker ///
305*be431cd8SAndroid Build Coastguard Worker /// # Safety
306*be431cd8SAndroid Build Coastguard Worker ///
307*be431cd8SAndroid Build Coastguard Worker /// This function has the same safety requirements as [`std::slice::from_raw_parts`],
308*be431cd8SAndroid Build Coastguard Worker /// but unlike that function, does not exhibit undefined behavior when `data` is a
309*be431cd8SAndroid Build Coastguard Worker /// null pointer and `len` is zero. In this case, it returns an empty slice.
slice_from_raw_parts_or_empty<'a, T>(data: *const T, len: usize) -> &'a [T]310*be431cd8SAndroid Build Coastguard Worker unsafe fn slice_from_raw_parts_or_empty<'a, T>(data: *const T, len: usize) -> &'a [T] {
311*be431cd8SAndroid Build Coastguard Worker if data.is_null() && len == 0 {
312*be431cd8SAndroid Build Coastguard Worker &[]
313*be431cd8SAndroid Build Coastguard Worker } else {
314*be431cd8SAndroid Build Coastguard Worker // SAFETY: The caller must guarantee to satisfy the safety requirements
315*be431cd8SAndroid Build Coastguard Worker // of the standard library function [`std::slice::from_raw_parts`].
316*be431cd8SAndroid Build Coastguard Worker unsafe { std::slice::from_raw_parts(data, len) }
317*be431cd8SAndroid Build Coastguard Worker }
318*be431cd8SAndroid Build Coastguard Worker }
319*be431cd8SAndroid Build Coastguard Worker
320*be431cd8SAndroid Build Coastguard Worker #[inline(always)]
ptr<T: Share>(txn: &MemTransaction, idx: usize) -> *mut T321*be431cd8SAndroid Build Coastguard Worker fn ptr<T: Share>(txn: &MemTransaction, idx: usize) -> *mut T {
322*be431cd8SAndroid Build Coastguard Worker let (base, region_idx) = if idx < txn.first.length {
323*be431cd8SAndroid Build Coastguard Worker (txn.first.address, idx)
324*be431cd8SAndroid Build Coastguard Worker } else {
325*be431cd8SAndroid Build Coastguard Worker (txn.second.address, idx - txn.first.length)
326*be431cd8SAndroid Build Coastguard Worker };
327*be431cd8SAndroid Build Coastguard Worker let byte_count: usize = region_idx.checked_mul(MessageQueue::<T>::type_size()).unwrap();
328*be431cd8SAndroid Build Coastguard Worker base.wrapping_byte_offset(byte_count.try_into().unwrap()) as *mut T
329*be431cd8SAndroid Build Coastguard Worker }
330*be431cd8SAndroid Build Coastguard Worker
331*be431cd8SAndroid Build Coastguard Worker #[inline(always)]
contiguous_count(txn: &MemTransaction, idx: usize, n_elems: usize) -> usize332*be431cd8SAndroid Build Coastguard Worker fn contiguous_count(txn: &MemTransaction, idx: usize, n_elems: usize) -> usize {
333*be431cd8SAndroid Build Coastguard Worker if idx > n_elems {
334*be431cd8SAndroid Build Coastguard Worker return 0;
335*be431cd8SAndroid Build Coastguard Worker }
336*be431cd8SAndroid Build Coastguard Worker let region_len = if idx < txn.first.length { txn.first.length } else { txn.second.length };
337*be431cd8SAndroid Build Coastguard Worker region_len - idx
338*be431cd8SAndroid Build Coastguard Worker }
339*be431cd8SAndroid Build Coastguard Worker
340*be431cd8SAndroid Build Coastguard Worker /** A read completion from the MessageQueue::read() method.
341*be431cd8SAndroid Build Coastguard Worker
342*be431cd8SAndroid Build Coastguard Worker This completion mutably borrows the MessageQueue to prevent concurrent reads;
343*be431cd8SAndroid Build Coastguard Worker these must be forbidden because the underlying AidlMessageQueue only stores the
344*be431cd8SAndroid Build Coastguard Worker number of outstanding reads, not which have and have not completed, so they
345*be431cd8SAndroid Build Coastguard Worker must complete in order. */
346*be431cd8SAndroid Build Coastguard Worker #[must_use]
347*be431cd8SAndroid Build Coastguard Worker pub struct ReadCompletion<'a, T: Share> {
348*be431cd8SAndroid Build Coastguard Worker inner: MemTransaction,
349*be431cd8SAndroid Build Coastguard Worker queue: &'a mut MessageQueue<T>,
350*be431cd8SAndroid Build Coastguard Worker n_elems: usize,
351*be431cd8SAndroid Build Coastguard Worker n_read: usize,
352*be431cd8SAndroid Build Coastguard Worker }
353*be431cd8SAndroid Build Coastguard Worker
354*be431cd8SAndroid Build Coastguard Worker impl<'a, T: Share> ReadCompletion<'a, T> {
355*be431cd8SAndroid Build Coastguard Worker /// Obtain a pointer to the location at which the idx'th item is located.
356*be431cd8SAndroid Build Coastguard Worker ///
357*be431cd8SAndroid Build Coastguard Worker /// The returned pointer is only valid while `self` has not been dropped and
358*be431cd8SAndroid Build Coastguard Worker /// is invalidated by any call to `self.read`. The pointer should be used
359*be431cd8SAndroid Build Coastguard Worker /// with `std::ptr::read` or a DMA API before calling `assume_read` to
360*be431cd8SAndroid Build Coastguard Worker /// indicate how many elements were read.
361*be431cd8SAndroid Build Coastguard Worker ///
362*be431cd8SAndroid Build Coastguard Worker /// It is only permitted to access at most `contiguous_count(idx)` items
363*be431cd8SAndroid Build Coastguard Worker /// via offsets from the returned address.
364*be431cd8SAndroid Build Coastguard Worker ///
365*be431cd8SAndroid Build Coastguard Worker /// Calling this method with a greater `idx` may return a pointer to another
366*be431cd8SAndroid Build Coastguard Worker /// memory region of different size than the first.
ptr(&self, idx: usize) -> *mut T367*be431cd8SAndroid Build Coastguard Worker pub fn ptr(&self, idx: usize) -> *mut T {
368*be431cd8SAndroid Build Coastguard Worker if idx >= self.n_elems {
369*be431cd8SAndroid Build Coastguard Worker panic!(
370*be431cd8SAndroid Build Coastguard Worker "indexing out of bound: ReadCompletion for {} elements but idx {} accessed",
371*be431cd8SAndroid Build Coastguard Worker self.n_elems, idx
372*be431cd8SAndroid Build Coastguard Worker )
373*be431cd8SAndroid Build Coastguard Worker }
374*be431cd8SAndroid Build Coastguard Worker ptr(&self.inner, idx)
375*be431cd8SAndroid Build Coastguard Worker }
376*be431cd8SAndroid Build Coastguard Worker
377*be431cd8SAndroid Build Coastguard Worker /// Return the number of contiguous elements located starting at the given
378*be431cd8SAndroid Build Coastguard Worker /// index in the backing buffer corresponding to the given index.
379*be431cd8SAndroid Build Coastguard Worker ///
380*be431cd8SAndroid Build Coastguard Worker /// Intended for use with the `ptr` method.
381*be431cd8SAndroid Build Coastguard Worker ///
382*be431cd8SAndroid Build Coastguard Worker /// Returns 0 if `idx` is greater than or equal to the completion's element
383*be431cd8SAndroid Build Coastguard Worker /// count.
contiguous_count(&self, idx: usize) -> usize384*be431cd8SAndroid Build Coastguard Worker pub fn contiguous_count(&self, idx: usize) -> usize {
385*be431cd8SAndroid Build Coastguard Worker contiguous_count(&self.inner, idx, self.n_elems)
386*be431cd8SAndroid Build Coastguard Worker }
387*be431cd8SAndroid Build Coastguard Worker
388*be431cd8SAndroid Build Coastguard Worker /// Returns how many elements still must be read from `self` before dropping
389*be431cd8SAndroid Build Coastguard Worker /// it.
unread_elements(&self) -> usize390*be431cd8SAndroid Build Coastguard Worker pub fn unread_elements(&self) -> usize {
391*be431cd8SAndroid Build Coastguard Worker assert!(self.n_read <= self.n_elems);
392*be431cd8SAndroid Build Coastguard Worker self.n_elems - self.n_read
393*be431cd8SAndroid Build Coastguard Worker }
394*be431cd8SAndroid Build Coastguard Worker
395*be431cd8SAndroid Build Coastguard Worker /// Read one item from the `self`. Fails and returns `()` if `self` is empty.
read(&mut self) -> Option<T>396*be431cd8SAndroid Build Coastguard Worker pub fn read(&mut self) -> Option<T> {
397*be431cd8SAndroid Build Coastguard Worker if self.unread_elements() > 0 {
398*be431cd8SAndroid Build Coastguard Worker // SAFETY: `self.ptr(self.n_read)`is known to be filled with a valid
399*be431cd8SAndroid Build Coastguard Worker // instance of type `T`.
400*be431cd8SAndroid Build Coastguard Worker let data = unsafe { self.ptr(self.n_read).read() };
401*be431cd8SAndroid Build Coastguard Worker self.n_read += 1;
402*be431cd8SAndroid Build Coastguard Worker Some(data)
403*be431cd8SAndroid Build Coastguard Worker } else {
404*be431cd8SAndroid Build Coastguard Worker None
405*be431cd8SAndroid Build Coastguard Worker }
406*be431cd8SAndroid Build Coastguard Worker }
407*be431cd8SAndroid Build Coastguard Worker
408*be431cd8SAndroid Build Coastguard Worker /// Promise to the `ReadCompletion` that `n_newly_read` elements have
409*be431cd8SAndroid Build Coastguard Worker /// been read with unsafe code or DMA from the pointer returned by the
410*be431cd8SAndroid Build Coastguard Worker /// `ptr` method.
411*be431cd8SAndroid Build Coastguard Worker ///
412*be431cd8SAndroid Build Coastguard Worker /// Panics if `n_newly_read` exceeds the number of elements still unread.
413*be431cd8SAndroid Build Coastguard Worker ///
414*be431cd8SAndroid Build Coastguard Worker /// Calling this method without actually reading the elements will result
415*be431cd8SAndroid Build Coastguard Worker /// in them being leaked without destructors (if any) running.
assume_read(&mut self, n_newly_read: usize)416*be431cd8SAndroid Build Coastguard Worker pub fn assume_read(&mut self, n_newly_read: usize) {
417*be431cd8SAndroid Build Coastguard Worker assert!(n_newly_read < self.unread_elements());
418*be431cd8SAndroid Build Coastguard Worker self.n_read += n_newly_read;
419*be431cd8SAndroid Build Coastguard Worker }
420*be431cd8SAndroid Build Coastguard Worker }
421*be431cd8SAndroid Build Coastguard Worker
422*be431cd8SAndroid Build Coastguard Worker impl<'a, T: Share> Drop for ReadCompletion<'a, T> {
drop(&mut self)423*be431cd8SAndroid Build Coastguard Worker fn drop(&mut self) {
424*be431cd8SAndroid Build Coastguard Worker if self.n_read < self.n_elems {
425*be431cd8SAndroid Build Coastguard Worker error!(
426*be431cd8SAndroid Build Coastguard Worker "ReadCompletion dropped without reading all elements ({}/{} read)",
427*be431cd8SAndroid Build Coastguard Worker self.n_read, self.n_elems
428*be431cd8SAndroid Build Coastguard Worker );
429*be431cd8SAndroid Build Coastguard Worker }
430*be431cd8SAndroid Build Coastguard Worker let txn = std::mem::take(&mut self.inner);
431*be431cd8SAndroid Build Coastguard Worker self.queue.commit_read(txn);
432*be431cd8SAndroid Build Coastguard Worker }
433*be431cd8SAndroid Build Coastguard Worker }
434*be431cd8SAndroid Build Coastguard Worker
435*be431cd8SAndroid Build Coastguard Worker impl<T: Share> MessageQueue<T> {
436*be431cd8SAndroid Build Coastguard Worker /// Begin a read transaction. The returned `ReadCompletion` can be used to
437*be431cd8SAndroid Build Coastguard Worker /// write into the region allocated for the transaction.
read(&mut self) -> Option<ReadCompletion<T>>438*be431cd8SAndroid Build Coastguard Worker pub fn read(&mut self) -> Option<ReadCompletion<T>> {
439*be431cd8SAndroid Build Coastguard Worker self.read_many(1)
440*be431cd8SAndroid Build Coastguard Worker }
441*be431cd8SAndroid Build Coastguard Worker
442*be431cd8SAndroid Build Coastguard Worker /// Begin a read transaction for multiple items. See `MessageQueue::read`.
read_many(&mut self, n: usize) -> Option<ReadCompletion<T>>443*be431cd8SAndroid Build Coastguard Worker pub fn read_many(&mut self, n: usize) -> Option<ReadCompletion<T>> {
444*be431cd8SAndroid Build Coastguard Worker let txn = self.begin_read(n)?;
445*be431cd8SAndroid Build Coastguard Worker Some(ReadCompletion { inner: txn, queue: self, n_elems: n, n_read: 0 })
446*be431cd8SAndroid Build Coastguard Worker }
447*be431cd8SAndroid Build Coastguard Worker
commit_read(&mut self, txn: MemTransaction) -> bool448*be431cd8SAndroid Build Coastguard Worker fn commit_read(&mut self, txn: MemTransaction) -> bool {
449*be431cd8SAndroid Build Coastguard Worker // SAFETY: simply calls commitRead with the txn length. The txn must
450*be431cd8SAndroid Build Coastguard Worker // only use its first MemRegion.
451*be431cd8SAndroid Build Coastguard Worker unsafe { self.inner.commitRead(txn.first.length + txn.second.length) }
452*be431cd8SAndroid Build Coastguard Worker }
453*be431cd8SAndroid Build Coastguard Worker
begin_read(&self, n: usize) -> Option<MemTransaction>454*be431cd8SAndroid Build Coastguard Worker fn begin_read(&self, n: usize) -> Option<MemTransaction> {
455*be431cd8SAndroid Build Coastguard Worker let mut txn: MemTransaction = Default::default();
456*be431cd8SAndroid Build Coastguard Worker // SAFETY: we pass a raw pointer to txn, which is used only during the
457*be431cd8SAndroid Build Coastguard Worker // call to beginRead to write the txn's MemRegion fields, which are raw
458*be431cd8SAndroid Build Coastguard Worker // pointers and lengths pointing into the queue. The pointer to txn is
459*be431cd8SAndroid Build Coastguard Worker // not stored.
460*be431cd8SAndroid Build Coastguard Worker unsafe { self.inner.beginRead(n, addr_of_mut!(txn)) }.then_some(txn)
461*be431cd8SAndroid Build Coastguard Worker }
462*be431cd8SAndroid Build Coastguard Worker }
463*be431cd8SAndroid Build Coastguard Worker
464*be431cd8SAndroid Build Coastguard Worker #[cfg(test)]
465*be431cd8SAndroid Build Coastguard Worker mod test {
466*be431cd8SAndroid Build Coastguard Worker use super::*;
467*be431cd8SAndroid Build Coastguard Worker
468*be431cd8SAndroid Build Coastguard Worker #[test]
slice_from_raw_parts_or_empty_with_nonempty()469*be431cd8SAndroid Build Coastguard Worker fn slice_from_raw_parts_or_empty_with_nonempty() {
470*be431cd8SAndroid Build Coastguard Worker const SLICE: &[u8] = &[1, 2, 3, 4, 5, 6];
471*be431cd8SAndroid Build Coastguard Worker // SAFETY: We are constructing a slice from the pointer and length of valid slice.
472*be431cd8SAndroid Build Coastguard Worker let from_raw_parts = unsafe {
473*be431cd8SAndroid Build Coastguard Worker let ptr = SLICE.as_ptr();
474*be431cd8SAndroid Build Coastguard Worker let len = SLICE.len();
475*be431cd8SAndroid Build Coastguard Worker slice_from_raw_parts_or_empty(ptr, len)
476*be431cd8SAndroid Build Coastguard Worker };
477*be431cd8SAndroid Build Coastguard Worker assert_eq!(SLICE, from_raw_parts);
478*be431cd8SAndroid Build Coastguard Worker }
479*be431cd8SAndroid Build Coastguard Worker
480*be431cd8SAndroid Build Coastguard Worker #[test]
slice_from_raw_parts_or_empty_with_null_pointer_zero_length()481*be431cd8SAndroid Build Coastguard Worker fn slice_from_raw_parts_or_empty_with_null_pointer_zero_length() {
482*be431cd8SAndroid Build Coastguard Worker // SAFETY: Calling `slice_from_raw_parts_or_empty` with a null pointer
483*be431cd8SAndroid Build Coastguard Worker // and a zero length is explicitly allowed by its safety requirements.
484*be431cd8SAndroid Build Coastguard Worker // In this case, `std::slice::from_raw_parts` has undefined behavior.
485*be431cd8SAndroid Build Coastguard Worker let empty_from_raw_parts = unsafe {
486*be431cd8SAndroid Build Coastguard Worker let ptr: *const u8 = std::ptr::null();
487*be431cd8SAndroid Build Coastguard Worker let len = 0;
488*be431cd8SAndroid Build Coastguard Worker slice_from_raw_parts_or_empty(ptr, len)
489*be431cd8SAndroid Build Coastguard Worker };
490*be431cd8SAndroid Build Coastguard Worker assert_eq!(&[] as &[u8], empty_from_raw_parts);
491*be431cd8SAndroid Build Coastguard Worker }
492*be431cd8SAndroid Build Coastguard Worker }
493