• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::ffi::CStr;
6 use std::ffi::CString;
7 
8 use libc::EINVAL;
9 use serde::Deserialize;
10 use serde::Serialize;
11 
12 use crate::descriptor::AsRawDescriptor;
13 use crate::descriptor::IntoRawDescriptor;
14 use crate::descriptor::SafeDescriptor;
15 use crate::Error;
16 use crate::RawDescriptor;
17 use crate::Result;
18 
19 /// A shared memory file descriptor and its size.
20 #[derive(Debug, Deserialize, Serialize)]
21 pub struct SharedMemory {
22     #[serde(with = "crate::with_as_descriptor")]
23     pub descriptor: SafeDescriptor,
24     pub size: u64,
25 }
26 
27 pub(crate) trait PlatformSharedMemory {
new(debug_name: &CStr, size: u64) -> Result<SharedMemory>28     fn new(debug_name: &CStr, size: u64) -> Result<SharedMemory>;
from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>29     fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>;
30 }
31 
32 impl SharedMemory {
33     /// Creates a new shared memory object of the given size.
34     ///
35     /// |name| is purely for debugging purposes. It does not need to be unique, and it does
36     /// not affect any non-debugging related properties of the constructed shared memory.
new<T: Into<Vec<u8>>>(debug_name: T, size: u64) -> Result<SharedMemory>37     pub fn new<T: Into<Vec<u8>>>(debug_name: T, size: u64) -> Result<SharedMemory> {
38         let debug_name = CString::new(debug_name).map_err(|_| super::Error::new(EINVAL))?;
39         <SharedMemory as PlatformSharedMemory>::new(&debug_name, size)
40     }
41 
42     /// Gets the size in bytes of the shared memory.
43     ///
44     /// The size returned here does not reflect changes by other interfaces or users of the shared
45     /// memory file descriptor.
size(&self) -> u6446     pub fn size(&self) -> u64 {
47         self.size
48     }
49 
50     /// Creates a SharedMemory instance from a SafeDescriptor owning a reference to a
51     /// shared memory descriptor. Ownership of the underlying descriptor is transferred to the
52     /// new SharedMemory object.
from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>53     pub fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory> {
54         <SharedMemory as PlatformSharedMemory>::from_safe_descriptor(descriptor, size)
55     }
56 
57     /// Clones the SharedMemory. The new SharedMemory will refer to the same
58     /// underlying object as the original.
try_clone(&self) -> Result<SharedMemory>59     pub fn try_clone(&self) -> Result<SharedMemory> {
60         let shmem_descriptor = SafeDescriptor::try_from(self as &dyn AsRawDescriptor)?;
61         SharedMemory::from_safe_descriptor(shmem_descriptor, self.size())
62     }
63 }
64 
65 /// USE THIS CAUTIOUSLY. On Windows, the returned handle is not a file handle and cannot be used as
66 /// if it were one. It is a handle to a the associated file mapping object and should only be used
67 /// for memory-mapping the file view.
68 impl AsRawDescriptor for SharedMemory {
as_raw_descriptor(&self) -> RawDescriptor69     fn as_raw_descriptor(&self) -> RawDescriptor {
70         self.descriptor.as_raw_descriptor()
71     }
72 }
73 
74 impl IntoRawDescriptor for SharedMemory {
into_raw_descriptor(self) -> RawDescriptor75     fn into_raw_descriptor(self) -> RawDescriptor {
76         self.descriptor.into_raw_descriptor()
77     }
78 }
79 
80 impl From<SharedMemory> for SafeDescriptor {
from(sm: SharedMemory) -> SafeDescriptor81     fn from(sm: SharedMemory) -> SafeDescriptor {
82         sm.descriptor
83     }
84 }
85 
86 impl audio_streams::shm_streams::SharedMemory for SharedMemory {
87     type Error = Error;
88 
anon(size: u64) -> Result<Self>89     fn anon(size: u64) -> Result<Self> {
90         SharedMemory::new("shm_streams", size)
91     }
92 
size(&self) -> u6493     fn size(&self) -> u64 {
94         self.size()
95     }
96 
97     #[cfg(any(target_os = "android", target_os = "linux"))]
as_raw_fd(&self) -> RawDescriptor98     fn as_raw_fd(&self) -> RawDescriptor {
99         self.as_raw_descriptor()
100     }
101 }
102 
103 #[cfg(test)]
104 mod tests {
105     use super::*;
106 
107     #[test]
new_1024()108     fn new_1024() {
109         let shm = SharedMemory::new("test", 1024).expect("failed to create shared memory");
110         assert_eq!(shm.size(), 1024);
111     }
112 
113     #[test]
new_1028()114     fn new_1028() {
115         let shm = SharedMemory::new("name", 1028).expect("failed to create shared memory");
116         assert_eq!(shm.size(), 1028);
117     }
118 
119     #[test]
new_too_huge()120     fn new_too_huge() {
121         SharedMemory::new("test", 0x8000_0000_0000_0000)
122             .expect_err("8 exabyte shared memory creation should fail");
123     }
124 }
125