use std::convert::TryInto;
use std::ffi::CStr;
use std::os::fd::AsRawFd;
use std::os::fd::IntoRawFd;
use std::os::unix::io::OwnedFd;
use libc::off_t;
use nix::sys::memfd::memfd_create;
use nix::sys::memfd::MemFdCreateFlag;
use nix::unistd::ftruncate;
use nix::unistd::sysconf;
use nix::unistd::SysconfVar;
use crate::rutabaga_os::descriptor::AsRawDescriptor;
use crate::rutabaga_os::descriptor::IntoRawDescriptor;
use crate::rutabaga_os::RawDescriptor;
use crate::rutabaga_utils::RutabagaError;
use crate::rutabaga_utils::RutabagaResult;
pub struct SharedMemory {
fd: OwnedFd,
size: u64,
}
impl SharedMemory {
pub fn new(debug_name: &CStr, size: u64) -> RutabagaResult<SharedMemory> {
let fd = memfd_create(
debug_name,
MemFdCreateFlag::MFD_CLOEXEC | MemFdCreateFlag::MFD_ALLOW_SEALING,
)?;
let size_off_t: off_t = size.try_into()?;
ftruncate(&fd, size_off_t)?;
Ok(SharedMemory { fd, size })
}
pub fn size(&self) -> u64 {
self.size
}
}
impl AsRawDescriptor for SharedMemory {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.fd.as_raw_fd()
}
}
impl IntoRawDescriptor for SharedMemory {
fn into_raw_descriptor(self) -> RawDescriptor {
self.fd.into_raw_fd()
}
}
pub fn round_up_to_page_size(v: u64) -> RutabagaResult<u64> {
let page_size_opt = sysconf(SysconfVar::PAGE_SIZE)?;
if let Some(page_size) = page_size_opt {
let page_mask = (page_size - 1) as u64;
let aligned_size = (v + page_mask) & !page_mask;
Ok(aligned_size)
} else {
Err(RutabagaError::SpecViolation("no page size"))
}
}