1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_void;
6*bb4ee6a4SAndroid Build Coastguard Worker use win_util::create_file_mapping;
7*bb4ee6a4SAndroid Build Coastguard Worker use win_util::duplicate_handle;
8*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winnt::PAGE_READWRITE;
9*bb4ee6a4SAndroid Build Coastguard Worker
10*bb4ee6a4SAndroid Build Coastguard Worker pub use super::mmap_platform::MemoryMappingArena;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsRawDescriptor;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::Descriptor;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::FromRawDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::MappedRegion;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemoryMapping as CrateMemoryMapping;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemoryMappingBuilder;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::MmapError as Error;
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::MmapResult as Result;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::Protection;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::RawDescriptor;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
22*bb4ee6a4SAndroid Build Coastguard Worker
23*bb4ee6a4SAndroid Build Coastguard Worker /// Validates that `offset`..`offset+range_size` lies within the bounds of a memory mapping of
24*bb4ee6a4SAndroid Build Coastguard Worker /// `mmap_size` bytes. Also checks for any overflow.
validate_includes_range(mmap_size: usize, offset: usize, range_size: usize) -> Result<()>25*bb4ee6a4SAndroid Build Coastguard Worker fn validate_includes_range(mmap_size: usize, offset: usize, range_size: usize) -> Result<()> {
26*bb4ee6a4SAndroid Build Coastguard Worker // Ensure offset + size doesn't overflow
27*bb4ee6a4SAndroid Build Coastguard Worker let end_offset = offset
28*bb4ee6a4SAndroid Build Coastguard Worker .checked_add(range_size)
29*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::InvalidAddress)?;
30*bb4ee6a4SAndroid Build Coastguard Worker // Ensure offset + size are within the mapping bounds
31*bb4ee6a4SAndroid Build Coastguard Worker if end_offset <= mmap_size {
32*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
33*bb4ee6a4SAndroid Build Coastguard Worker } else {
34*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::InvalidAddress)
35*bb4ee6a4SAndroid Build Coastguard Worker }
36*bb4ee6a4SAndroid Build Coastguard Worker }
37*bb4ee6a4SAndroid Build Coastguard Worker
38*bb4ee6a4SAndroid Build Coastguard Worker impl dyn MappedRegion {
39*bb4ee6a4SAndroid Build Coastguard Worker /// Calls msync with MS_SYNC on a mapping of `size` bytes starting at `offset` from the start of
40*bb4ee6a4SAndroid Build Coastguard Worker /// the region. `offset`..`offset+size` must be contained within the `MappedRegion`.
msync(&self, offset: usize, size: usize) -> Result<()>41*bb4ee6a4SAndroid Build Coastguard Worker pub fn msync(&self, offset: usize, size: usize) -> Result<()> {
42*bb4ee6a4SAndroid Build Coastguard Worker validate_includes_range(self.size(), offset, size)?;
43*bb4ee6a4SAndroid Build Coastguard Worker
44*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
45*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the MemoryMapping/MemoryMappingArena interface ensures our pointer and size
46*bb4ee6a4SAndroid Build Coastguard Worker // are correct, and we've validated that `offset`..`offset+size` is in the range owned by
47*bb4ee6a4SAndroid Build Coastguard Worker // this `MappedRegion`.
48*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
49*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::memoryapi::FlushViewOfFile;
50*bb4ee6a4SAndroid Build Coastguard Worker if FlushViewOfFile((self.as_ptr() as usize + offset) as *mut libc::c_void, size) == 0 {
51*bb4ee6a4SAndroid Build Coastguard Worker -1
52*bb4ee6a4SAndroid Build Coastguard Worker } else {
53*bb4ee6a4SAndroid Build Coastguard Worker 0
54*bb4ee6a4SAndroid Build Coastguard Worker }
55*bb4ee6a4SAndroid Build Coastguard Worker };
56*bb4ee6a4SAndroid Build Coastguard Worker if ret != -1 {
57*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
58*bb4ee6a4SAndroid Build Coastguard Worker } else {
59*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::SystemCallFailed(super::Error::last()))
60*bb4ee6a4SAndroid Build Coastguard Worker }
61*bb4ee6a4SAndroid Build Coastguard Worker }
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker
64*bb4ee6a4SAndroid Build Coastguard Worker /// Wraps an anonymous shared memory mapping in the current process. Provides
65*bb4ee6a4SAndroid Build Coastguard Worker /// RAII semantics including munmap when no longer needed.
66*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
67*bb4ee6a4SAndroid Build Coastguard Worker pub struct MemoryMapping {
68*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) addr: *mut c_void,
69*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) size: usize,
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker
72*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
73*bb4ee6a4SAndroid Build Coastguard Worker // Send and Sync aren't automatically inherited for the raw address pointer.
74*bb4ee6a4SAndroid Build Coastguard Worker // Accessing that pointer is only done through the stateless interface which
75*bb4ee6a4SAndroid Build Coastguard Worker // allows the object to be shared by multiple threads without a decrease in
76*bb4ee6a4SAndroid Build Coastguard Worker // safety.
77*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for MemoryMapping {}
78*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: See comments for impl Send
79*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for MemoryMapping {}
80*bb4ee6a4SAndroid Build Coastguard Worker
81*bb4ee6a4SAndroid Build Coastguard Worker impl MemoryMapping {
82*bb4ee6a4SAndroid Build Coastguard Worker /// Creates an anonymous shared, read/write mapping of `size` bytes.
83*bb4ee6a4SAndroid Build Coastguard Worker ///
84*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
85*bb4ee6a4SAndroid Build Coastguard Worker /// * `size` - Size of memory region in bytes.
new(size: usize) -> Result<MemoryMapping>86*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(size: usize) -> Result<MemoryMapping> {
87*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::new_protection(size, Protection::read_write())
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker
90*bb4ee6a4SAndroid Build Coastguard Worker /// Maps the first `size` bytes of the given `descriptor` as read/write.
91*bb4ee6a4SAndroid Build Coastguard Worker ///
92*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
93*bb4ee6a4SAndroid Build Coastguard Worker /// * `file_handle` - File handle to map from.
94*bb4ee6a4SAndroid Build Coastguard Worker /// * `size` - Size of memory region in bytes.
from_descriptor( file_handle: &dyn AsRawDescriptor, size: usize, ) -> Result<MemoryMapping>95*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_descriptor(
96*bb4ee6a4SAndroid Build Coastguard Worker file_handle: &dyn AsRawDescriptor,
97*bb4ee6a4SAndroid Build Coastguard Worker size: usize,
98*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<MemoryMapping> {
99*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::from_descriptor_offset(file_handle, size, 0)
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker
from_raw_descriptor(file_handle: RawDescriptor, size: usize) -> Result<MemoryMapping>102*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_raw_descriptor(file_handle: RawDescriptor, size: usize) -> Result<MemoryMapping> {
103*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::from_descriptor_offset(&Descriptor(file_handle), size, 0)
104*bb4ee6a4SAndroid Build Coastguard Worker }
105*bb4ee6a4SAndroid Build Coastguard Worker
from_descriptor_offset( file_handle: &dyn AsRawDescriptor, size: usize, offset: u64, ) -> Result<MemoryMapping>106*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_descriptor_offset(
107*bb4ee6a4SAndroid Build Coastguard Worker file_handle: &dyn AsRawDescriptor,
108*bb4ee6a4SAndroid Build Coastguard Worker size: usize,
109*bb4ee6a4SAndroid Build Coastguard Worker offset: u64,
110*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<MemoryMapping> {
111*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::from_descriptor_offset_protection(
112*bb4ee6a4SAndroid Build Coastguard Worker file_handle,
113*bb4ee6a4SAndroid Build Coastguard Worker size,
114*bb4ee6a4SAndroid Build Coastguard Worker offset,
115*bb4ee6a4SAndroid Build Coastguard Worker Protection::read_write(),
116*bb4ee6a4SAndroid Build Coastguard Worker )
117*bb4ee6a4SAndroid Build Coastguard Worker }
118*bb4ee6a4SAndroid Build Coastguard Worker
119*bb4ee6a4SAndroid Build Coastguard Worker // Check that offset+count is valid and return the sum.
range_end(&self, offset: usize, count: usize) -> Result<usize>120*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn range_end(&self, offset: usize, count: usize) -> Result<usize> {
121*bb4ee6a4SAndroid Build Coastguard Worker let mem_end = offset.checked_add(count).ok_or(Error::InvalidAddress)?;
122*bb4ee6a4SAndroid Build Coastguard Worker if mem_end > self.size() {
123*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::InvalidAddress);
124*bb4ee6a4SAndroid Build Coastguard Worker }
125*bb4ee6a4SAndroid Build Coastguard Worker Ok(mem_end)
126*bb4ee6a4SAndroid Build Coastguard Worker }
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker
129*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
130*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the pointer and size point to a memory range owned by this MemoryMapping that won't
131*bb4ee6a4SAndroid Build Coastguard Worker // be unmapped until it's Dropped.
132*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl MappedRegion for MemoryMapping {
as_ptr(&self) -> *mut u8133*bb4ee6a4SAndroid Build Coastguard Worker fn as_ptr(&self) -> *mut u8 {
134*bb4ee6a4SAndroid Build Coastguard Worker self.addr as *mut u8
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker
size(&self) -> usize137*bb4ee6a4SAndroid Build Coastguard Worker fn size(&self) -> usize {
138*bb4ee6a4SAndroid Build Coastguard Worker self.size
139*bb4ee6a4SAndroid Build Coastguard Worker }
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker
142*bb4ee6a4SAndroid Build Coastguard Worker impl CrateMemoryMapping {
from_raw_ptr(addr: RawDescriptor, size: usize) -> Result<CrateMemoryMapping>143*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_raw_ptr(addr: RawDescriptor, size: usize) -> Result<CrateMemoryMapping> {
144*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::from_raw_ptr(addr, size).map(|mapping| CrateMemoryMapping {
145*bb4ee6a4SAndroid Build Coastguard Worker mapping,
146*bb4ee6a4SAndroid Build Coastguard Worker _file_descriptor: None,
147*bb4ee6a4SAndroid Build Coastguard Worker })
148*bb4ee6a4SAndroid Build Coastguard Worker }
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker
151*bb4ee6a4SAndroid Build Coastguard Worker pub trait MemoryMappingBuilderWindows<'a> {
152*bb4ee6a4SAndroid Build Coastguard Worker /// Build the memory mapping given the specified descriptor to mapped memory
153*bb4ee6a4SAndroid Build Coastguard Worker ///
154*bb4ee6a4SAndroid Build Coastguard Worker /// Default: Create a new memory mapping.
155*bb4ee6a4SAndroid Build Coastguard Worker ///
156*bb4ee6a4SAndroid Build Coastguard Worker /// descriptor MUST be a mapping handle. Files MUST use `MemoryMappingBuilder::from_file`
157*bb4ee6a4SAndroid Build Coastguard Worker /// instead.
158*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::wrong_self_convention)]
from_descriptor(self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder159*bb4ee6a4SAndroid Build Coastguard Worker fn from_descriptor(self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder;
160*bb4ee6a4SAndroid Build Coastguard Worker }
161*bb4ee6a4SAndroid Build Coastguard Worker
162*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> MemoryMappingBuilderWindows<'a> for MemoryMappingBuilder<'a> {
163*bb4ee6a4SAndroid Build Coastguard Worker /// See MemoryMappingBuilderWindows.
from_descriptor(mut self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder164*bb4ee6a4SAndroid Build Coastguard Worker fn from_descriptor(mut self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder {
165*bb4ee6a4SAndroid Build Coastguard Worker self.descriptor = Some(descriptor);
166*bb4ee6a4SAndroid Build Coastguard Worker self
167*bb4ee6a4SAndroid Build Coastguard Worker }
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker
170*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> MemoryMappingBuilder<'a> {
171*bb4ee6a4SAndroid Build Coastguard Worker /// Build a MemoryMapping from the provided options.
build(self) -> Result<CrateMemoryMapping>172*bb4ee6a4SAndroid Build Coastguard Worker pub fn build(self) -> Result<CrateMemoryMapping> {
173*bb4ee6a4SAndroid Build Coastguard Worker match self.descriptor {
174*bb4ee6a4SAndroid Build Coastguard Worker Some(descriptor) => {
175*bb4ee6a4SAndroid Build Coastguard Worker let mapping_descriptor = if self.is_file_descriptor {
176*bb4ee6a4SAndroid Build Coastguard Worker // On Windows, a file cannot be mmapped directly. We have to create a mapping
177*bb4ee6a4SAndroid Build Coastguard Worker // handle for it first. That handle is then provided to Self::wrap, which
178*bb4ee6a4SAndroid Build Coastguard Worker // performs the actual mmap (creating a mapped view).
179*bb4ee6a4SAndroid Build Coastguard Worker //
180*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
181*bb4ee6a4SAndroid Build Coastguard Worker // Safe because self.descriptor is guaranteed to be a valid handle.
182*bb4ee6a4SAndroid Build Coastguard Worker let mapping_handle = unsafe {
183*bb4ee6a4SAndroid Build Coastguard Worker create_file_mapping(
184*bb4ee6a4SAndroid Build Coastguard Worker Some(descriptor.as_raw_descriptor()),
185*bb4ee6a4SAndroid Build Coastguard Worker self.size as u64,
186*bb4ee6a4SAndroid Build Coastguard Worker PAGE_READWRITE,
187*bb4ee6a4SAndroid Build Coastguard Worker None,
188*bb4ee6a4SAndroid Build Coastguard Worker )
189*bb4ee6a4SAndroid Build Coastguard Worker }
190*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::StdSyscallFailed)?;
191*bb4ee6a4SAndroid Build Coastguard Worker
192*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
193*bb4ee6a4SAndroid Build Coastguard Worker // The above comment block is why the SafeDescriptor wrap is safe.
194*bb4ee6a4SAndroid Build Coastguard Worker Some(unsafe { SafeDescriptor::from_raw_descriptor(mapping_handle) })
195*bb4ee6a4SAndroid Build Coastguard Worker } else {
196*bb4ee6a4SAndroid Build Coastguard Worker None
197*bb4ee6a4SAndroid Build Coastguard Worker };
198*bb4ee6a4SAndroid Build Coastguard Worker
199*bb4ee6a4SAndroid Build Coastguard Worker MemoryMappingBuilder::wrap(
200*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::from_descriptor_offset_protection(
201*bb4ee6a4SAndroid Build Coastguard Worker match mapping_descriptor.as_ref() {
202*bb4ee6a4SAndroid Build Coastguard Worker Some(descriptor) => descriptor as &dyn AsRawDescriptor,
203*bb4ee6a4SAndroid Build Coastguard Worker None => descriptor,
204*bb4ee6a4SAndroid Build Coastguard Worker },
205*bb4ee6a4SAndroid Build Coastguard Worker self.size,
206*bb4ee6a4SAndroid Build Coastguard Worker self.offset.unwrap_or(0),
207*bb4ee6a4SAndroid Build Coastguard Worker self.protection.unwrap_or_else(Protection::read_write),
208*bb4ee6a4SAndroid Build Coastguard Worker )?,
209*bb4ee6a4SAndroid Build Coastguard Worker if self.is_file_descriptor {
210*bb4ee6a4SAndroid Build Coastguard Worker self.descriptor
211*bb4ee6a4SAndroid Build Coastguard Worker } else {
212*bb4ee6a4SAndroid Build Coastguard Worker None
213*bb4ee6a4SAndroid Build Coastguard Worker },
214*bb4ee6a4SAndroid Build Coastguard Worker )
215*bb4ee6a4SAndroid Build Coastguard Worker }
216*bb4ee6a4SAndroid Build Coastguard Worker None => MemoryMappingBuilder::wrap(
217*bb4ee6a4SAndroid Build Coastguard Worker MemoryMapping::new_protection(
218*bb4ee6a4SAndroid Build Coastguard Worker self.size,
219*bb4ee6a4SAndroid Build Coastguard Worker self.protection.unwrap_or_else(Protection::read_write),
220*bb4ee6a4SAndroid Build Coastguard Worker )?,
221*bb4ee6a4SAndroid Build Coastguard Worker None,
222*bb4ee6a4SAndroid Build Coastguard Worker ),
223*bb4ee6a4SAndroid Build Coastguard Worker }
224*bb4ee6a4SAndroid Build Coastguard Worker }
wrap( mapping: MemoryMapping, file_descriptor: Option<&'a dyn AsRawDescriptor>, ) -> Result<CrateMemoryMapping>225*bb4ee6a4SAndroid Build Coastguard Worker pub fn wrap(
226*bb4ee6a4SAndroid Build Coastguard Worker mapping: MemoryMapping,
227*bb4ee6a4SAndroid Build Coastguard Worker file_descriptor: Option<&'a dyn AsRawDescriptor>,
228*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<CrateMemoryMapping> {
229*bb4ee6a4SAndroid Build Coastguard Worker let file_descriptor = match file_descriptor {
230*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
231*bb4ee6a4SAndroid Build Coastguard Worker // Safe because `duplicate_handle` will return a handle or at least error out.
232*bb4ee6a4SAndroid Build Coastguard Worker Some(descriptor) => unsafe {
233*bb4ee6a4SAndroid Build Coastguard Worker Some(SafeDescriptor::from_raw_descriptor(
234*bb4ee6a4SAndroid Build Coastguard Worker duplicate_handle(descriptor.as_raw_descriptor())
235*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::StdSyscallFailed)?,
236*bb4ee6a4SAndroid Build Coastguard Worker ))
237*bb4ee6a4SAndroid Build Coastguard Worker },
238*bb4ee6a4SAndroid Build Coastguard Worker None => None,
239*bb4ee6a4SAndroid Build Coastguard Worker };
240*bb4ee6a4SAndroid Build Coastguard Worker
241*bb4ee6a4SAndroid Build Coastguard Worker Ok(CrateMemoryMapping {
242*bb4ee6a4SAndroid Build Coastguard Worker mapping,
243*bb4ee6a4SAndroid Build Coastguard Worker _file_descriptor: file_descriptor,
244*bb4ee6a4SAndroid Build Coastguard Worker })
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker
248*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
249*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
250*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
251*bb4ee6a4SAndroid Build Coastguard Worker use crate::SharedMemory;
252*bb4ee6a4SAndroid Build Coastguard Worker use crate::VolatileMemory;
253*bb4ee6a4SAndroid Build Coastguard Worker use crate::VolatileMemoryError;
254*bb4ee6a4SAndroid Build Coastguard Worker
255*bb4ee6a4SAndroid Build Coastguard Worker // get_slice() and other methods are only available on crate::MemoryMapping.
to_crate_mmap(mapping: MemoryMapping) -> crate::MemoryMapping256*bb4ee6a4SAndroid Build Coastguard Worker fn to_crate_mmap(mapping: MemoryMapping) -> crate::MemoryMapping {
257*bb4ee6a4SAndroid Build Coastguard Worker crate::MemoryMapping {
258*bb4ee6a4SAndroid Build Coastguard Worker mapping,
259*bb4ee6a4SAndroid Build Coastguard Worker _file_descriptor: None,
260*bb4ee6a4SAndroid Build Coastguard Worker }
261*bb4ee6a4SAndroid Build Coastguard Worker }
262*bb4ee6a4SAndroid Build Coastguard Worker
263*bb4ee6a4SAndroid Build Coastguard Worker #[test]
basic_map()264*bb4ee6a4SAndroid Build Coastguard Worker fn basic_map() {
265*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::new("test", 1028).unwrap();
266*bb4ee6a4SAndroid Build Coastguard Worker let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 1024).unwrap());
267*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(1024, m.size());
268*bb4ee6a4SAndroid Build Coastguard Worker }
269*bb4ee6a4SAndroid Build Coastguard Worker
270*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_write_past_end()271*bb4ee6a4SAndroid Build Coastguard Worker fn test_write_past_end() {
272*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::new("test", 1028).unwrap();
273*bb4ee6a4SAndroid Build Coastguard Worker let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
274*bb4ee6a4SAndroid Build Coastguard Worker let res = m.write_slice(&[1, 2, 3, 4, 5, 6], 0);
275*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.is_ok());
276*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.unwrap(), 5);
277*bb4ee6a4SAndroid Build Coastguard Worker }
278*bb4ee6a4SAndroid Build Coastguard Worker
279*bb4ee6a4SAndroid Build Coastguard Worker #[test]
slice_size()280*bb4ee6a4SAndroid Build Coastguard Worker fn slice_size() {
281*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::new("test", 1028).unwrap();
282*bb4ee6a4SAndroid Build Coastguard Worker let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
283*bb4ee6a4SAndroid Build Coastguard Worker let s = m.get_slice(2, 3).unwrap();
284*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(s.size(), 3);
285*bb4ee6a4SAndroid Build Coastguard Worker }
286*bb4ee6a4SAndroid Build Coastguard Worker
287*bb4ee6a4SAndroid Build Coastguard Worker #[test]
slice_addr()288*bb4ee6a4SAndroid Build Coastguard Worker fn slice_addr() {
289*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::new("test", 1028).unwrap();
290*bb4ee6a4SAndroid Build Coastguard Worker let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
291*bb4ee6a4SAndroid Build Coastguard Worker let s = m.get_slice(2, 3).unwrap();
292*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: trivially safe
293*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(s.as_ptr(), unsafe { m.as_ptr().offset(2) });
294*bb4ee6a4SAndroid Build Coastguard Worker }
295*bb4ee6a4SAndroid Build Coastguard Worker
296*bb4ee6a4SAndroid Build Coastguard Worker #[test]
slice_overflow_error()297*bb4ee6a4SAndroid Build Coastguard Worker fn slice_overflow_error() {
298*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::new("test", 1028).unwrap();
299*bb4ee6a4SAndroid Build Coastguard Worker let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
300*bb4ee6a4SAndroid Build Coastguard Worker let res = m.get_slice(usize::MAX, 3).unwrap_err();
301*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
302*bb4ee6a4SAndroid Build Coastguard Worker res,
303*bb4ee6a4SAndroid Build Coastguard Worker VolatileMemoryError::Overflow {
304*bb4ee6a4SAndroid Build Coastguard Worker base: usize::MAX,
305*bb4ee6a4SAndroid Build Coastguard Worker offset: 3,
306*bb4ee6a4SAndroid Build Coastguard Worker }
307*bb4ee6a4SAndroid Build Coastguard Worker );
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker #[test]
slice_oob_error()310*bb4ee6a4SAndroid Build Coastguard Worker fn slice_oob_error() {
311*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::new("test", 1028).unwrap();
312*bb4ee6a4SAndroid Build Coastguard Worker let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
313*bb4ee6a4SAndroid Build Coastguard Worker let res = m.get_slice(3, 3).unwrap_err();
314*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, VolatileMemoryError::OutOfBounds { addr: 6 });
315*bb4ee6a4SAndroid Build Coastguard Worker }
316*bb4ee6a4SAndroid Build Coastguard Worker }
317