xref: /aosp_15_r20/external/crosvm/base/src/shm.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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::SafeDescriptor;
14 use crate::Error;
15 use crate::RawDescriptor;
16 use crate::Result;
17 
18 /// A shared memory file descriptor and its size.
19 #[derive(Debug, Deserialize, Serialize)]
20 pub struct SharedMemory {
21     #[serde(with = "crate::with_as_descriptor")]
22     pub descriptor: SafeDescriptor,
23     pub size: u64,
24 }
25 
26 pub(crate) trait PlatformSharedMemory {
new(debug_name: &CStr, size: u64) -> Result<SharedMemory>27     fn new(debug_name: &CStr, size: u64) -> Result<SharedMemory>;
from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>28     fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>;
29 }
30 
31 impl SharedMemory {
32     /// Creates a new shared memory object of the given size.
33     ///
34     /// |name| is purely for debugging purposes. It does not need to be unique, and it does
35     /// not affect any non-debugging related properties of the constructed shared memory.
new<T: Into<Vec<u8>>>(debug_name: T, size: u64) -> Result<SharedMemory>36     pub fn new<T: Into<Vec<u8>>>(debug_name: T, size: u64) -> Result<SharedMemory> {
37         let debug_name = CString::new(debug_name).map_err(|_| super::Error::new(EINVAL))?;
38         <SharedMemory as PlatformSharedMemory>::new(&debug_name, size)
39     }
40 
41     /// Gets the size in bytes of the shared memory.
42     ///
43     /// The size returned here does not reflect changes by other interfaces or users of the shared
44     /// memory file descriptor.
size(&self) -> u6445     pub fn size(&self) -> u64 {
46         self.size
47     }
48 
49     /// Creates a SharedMemory instance from a SafeDescriptor owning a reference to a
50     /// shared memory descriptor. Ownership of the underlying descriptor is transferred to the
51     /// new SharedMemory object.
from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>52     pub fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory> {
53         <SharedMemory as PlatformSharedMemory>::from_safe_descriptor(descriptor, size)
54     }
55 
56     /// Clones the SharedMemory. The new SharedMemory will refer to the same
57     /// underlying object as the original.
try_clone(&self) -> Result<SharedMemory>58     pub fn try_clone(&self) -> Result<SharedMemory> {
59         Ok(SharedMemory {
60             descriptor: self.descriptor.try_clone()?,
61             size: self.size,
62         })
63     }
64 }
65 
66 /// USE THIS CAUTIOUSLY. On Windows, the returned handle is not a file handle and cannot be used as
67 /// if it were one. It is a handle to a the associated file mapping object and should only be used
68 /// for memory-mapping the file view.
69 impl AsRawDescriptor for SharedMemory {
as_raw_descriptor(&self) -> RawDescriptor70     fn as_raw_descriptor(&self) -> RawDescriptor {
71         self.descriptor.as_raw_descriptor()
72     }
73 }
74 
75 impl From<SharedMemory> for SafeDescriptor {
from(sm: SharedMemory) -> SafeDescriptor76     fn from(sm: SharedMemory) -> SafeDescriptor {
77         sm.descriptor
78     }
79 }
80 
81 impl audio_streams::shm_streams::SharedMemory for SharedMemory {
82     type Error = Error;
83 
anon(size: u64) -> Result<Self>84     fn anon(size: u64) -> Result<Self> {
85         SharedMemory::new("shm_streams", size)
86     }
87 
size(&self) -> u6488     fn size(&self) -> u64 {
89         self.size()
90     }
91 
92     #[cfg(any(target_os = "android", target_os = "linux"))]
as_raw_fd(&self) -> RawDescriptor93     fn as_raw_fd(&self) -> RawDescriptor {
94         self.as_raw_descriptor()
95     }
96 }
97 
98 #[cfg(test)]
99 mod tests {
100     use super::*;
101 
102     #[test]
new_1024()103     fn new_1024() {
104         let shm = SharedMemory::new("test", 1024).expect("failed to create shared memory");
105         assert_eq!(shm.size(), 1024);
106     }
107 
108     #[test]
new_1028()109     fn new_1028() {
110         let shm = SharedMemory::new("name", 1028).expect("failed to create shared memory");
111         assert_eq!(shm.size(), 1028);
112     }
113 
114     #[test]
new_too_huge()115     fn new_too_huge() {
116         SharedMemory::new("test", 0x8000_0000_0000_0000)
117             .expect_err("8 exabyte shared memory creation should fail");
118     }
119 }
120