• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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::convert::TryInto;
6 use std::ffi::CStr;
7 use std::os::unix::io::OwnedFd;
8 
9 use libc::off_t;
10 use nix::sys::memfd::memfd_create;
11 use nix::sys::memfd::MemFdCreateFlag;
12 use nix::unistd::ftruncate;
13 use nix::unistd::sysconf;
14 use nix::unistd::SysconfVar;
15 
16 use crate::rutabaga_os::descriptor::AsRawDescriptor;
17 use crate::rutabaga_os::descriptor::IntoRawDescriptor;
18 use crate::rutabaga_os::RawDescriptor;
19 use crate::rutabaga_utils::RutabagaError;
20 use crate::rutabaga_utils::RutabagaResult;
21 
22 pub struct SharedMemory {
23     fd: OwnedFd,
24     size: u64,
25 }
26 
27 impl SharedMemory {
28     /// Creates a new shared memory file descriptor with zero size.
29     ///
30     /// If a name is given, it will appear in `/proc/self/fd/<shm fd>` for the purposes of
31     /// debugging. The name does not need to be unique.
32     ///
33     /// The file descriptor is opened with the close on exec flag and allows memfd sealing.
new(debug_name: &CStr, size: u64) -> RutabagaResult<SharedMemory>34     pub fn new(debug_name: &CStr, size: u64) -> RutabagaResult<SharedMemory> {
35         let fd = memfd_create(
36             debug_name,
37             MemFdCreateFlag::MFD_CLOEXEC | MemFdCreateFlag::MFD_ALLOW_SEALING,
38         )?;
39 
40         let size_off_t: off_t = size.try_into()?;
41         ftruncate(&fd, size_off_t)?;
42 
43         Ok(SharedMemory { fd, size })
44     }
45 
46     /// Gets the size in bytes of the shared memory.
47     ///
48     /// The size returned here does not reflect changes by other interfaces or users of the shared
49     /// memory file descriptor..
size(&self) -> u6450     pub fn size(&self) -> u64 {
51         self.size
52     }
53 }
54 
55 impl AsRawDescriptor for SharedMemory {
as_raw_descriptor(&self) -> RawDescriptor56     fn as_raw_descriptor(&self) -> RawDescriptor {
57         self.fd.as_raw_descriptor()
58     }
59 }
60 
61 impl IntoRawDescriptor for SharedMemory {
into_raw_descriptor(self) -> RawDescriptor62     fn into_raw_descriptor(self) -> RawDescriptor {
63         self.fd.into_raw_descriptor()
64     }
65 }
66 
67 /// Uses the system's page size in bytes to round the given value up to the nearest page boundary.
round_up_to_page_size(v: u64) -> RutabagaResult<u64>68 pub fn round_up_to_page_size(v: u64) -> RutabagaResult<u64> {
69     let page_size_opt = sysconf(SysconfVar::PAGE_SIZE)?;
70     if let Some(page_size) = page_size_opt {
71         let page_mask = (page_size - 1) as u64;
72         let aligned_size = (v + page_mask) & !page_mask;
73         Ok(aligned_size)
74     } else {
75         Err(RutabagaError::SpecViolation("no page size"))
76     }
77 }
78