shared-memory: formatting

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-12-07 11:52:58 +01:00
parent 1185458719
commit fd39f876dc
3 changed files with 65 additions and 58 deletions

View File

@ -1,20 +1,20 @@
use std::path::Path;
use std::os::unix::io::AsRawFd;
use std::mem::MaybeUninit;
use std::fs::File;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::FromRawFd;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::fs::File;
use std::mem::MaybeUninit;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::FromRawFd;
use std::path::Path;
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
use nix::errno::Errno;
use nix::fcntl::OFlag; use nix::fcntl::OFlag;
use nix::sys::mman::{MapFlags, ProtFlags}; use nix::sys::mman::{MapFlags, ProtFlags};
use nix::sys::stat::Mode; use nix::sys::stat::Mode;
use nix::errno::Errno;
use proxmox_sys::error::SysError;
use proxmox_sys::fs::CreateOptions; use proxmox_sys::fs::CreateOptions;
use proxmox_sys::mmap::Mmap; use proxmox_sys::mmap::Mmap;
use proxmox_sys::error::SysError;
mod raw_shared_mutex; mod raw_shared_mutex;
@ -31,7 +31,9 @@ pub trait Init: Sized {
fn initialize(this: &mut MaybeUninit<Self>); fn initialize(this: &mut MaybeUninit<Self>);
/// Check if the data has the correct format /// Check if the data has the correct format
fn check_type_magic(_this: &MaybeUninit<Self>) -> Result<(), Error> { Ok(()) } fn check_type_magic(_this: &MaybeUninit<Self>) -> Result<(), Error> {
Ok(())
}
} }
/// Memory mapped shared memory region /// Memory mapped shared memory region
@ -45,7 +47,7 @@ pub struct SharedMemory<T> {
mmap: Mmap<T>, mmap: Mmap<T>,
} }
const fn up_to_page_size(n: usize) -> usize { const fn up_to_page_size(n: usize) -> usize {
// FIXME: use sysconf(_SC_PAGE_SIZE) // FIXME: use sysconf(_SC_PAGE_SIZE)
(n + 4095) & !4095 (n + 4095) & !4095
} }
@ -55,7 +57,8 @@ fn mmap_file<T: Init>(file: &mut File, initialize: bool) -> Result<Mmap<T>, Erro
let mut mmap: Mmap<MaybeUninit<T>> = unsafe { let mut mmap: Mmap<MaybeUninit<T>> = unsafe {
Mmap::map_fd( Mmap::map_fd(
file.as_raw_fd(), file.as_raw_fd(),
0, 1, 0,
1,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_SHARED | MapFlags::MAP_NORESERVE | MapFlags::MAP_POPULATE, MapFlags::MAP_SHARED | MapFlags::MAP_NORESERVE | MapFlags::MAP_POPULATE,
)? )?
@ -73,15 +76,17 @@ fn mmap_file<T: Init>(file: &mut File, initialize: bool) -> Result<Mmap<T>, Erro
Ok(unsafe { std::mem::transmute(mmap) }) Ok(unsafe { std::mem::transmute(mmap) })
} }
impl <T: Sized + Init> SharedMemory<T> { impl<T: Sized + Init> SharedMemory<T> {
pub fn open(path: &Path, options: CreateOptions) -> Result<Self, Error> { pub fn open(path: &Path, options: CreateOptions) -> Result<Self, Error> {
let size = std::mem::size_of::<T>(); let size = std::mem::size_of::<T>();
let up_size = up_to_page_size(size); let up_size = up_to_page_size(size);
if size != up_size { if size != up_size {
bail!("SharedMemory::open {:?} failed - data size {} is not a multiple of 4096", path, size); bail!(
"SharedMemory::open {:?} failed - data size {} is not a multiple of 4096",
path,
size
);
} }
let mmap = Self::open_shmem(path, options)?; let mmap = Self::open_shmem(path, options)?;
@ -89,10 +94,7 @@ impl <T: Sized + Init> SharedMemory<T> {
Ok(Self { mmap }) Ok(Self { mmap })
} }
pub fn open_shmem<P: AsRef<Path>>( pub fn open_shmem<P: AsRef<Path>>(path: P, options: CreateOptions) -> Result<Mmap<T>, Error> {
path: P,
options: CreateOptions,
) -> Result<Mmap<T>, Error> {
let path = path.as_ref(); let path = path.as_ref();
let dir_name = path let dir_name = path
@ -177,7 +179,7 @@ impl <T: Sized + Init> SharedMemory<T> {
Err(err) => bail!("open {:?} failed - {}", path, err), Err(err) => bail!("open {:?} failed - {}", path, err),
} }
} }
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
} }
} }
@ -188,7 +190,6 @@ impl <T: Sized + Init> SharedMemory<T> {
pub fn data_mut(&mut self) -> &mut T { pub fn data_mut(&mut self) -> &mut T {
&mut self.mmap[0] &mut self.mmap[0]
} }
} }
/// Helper to initialize nested data /// Helper to initialize nested data
@ -217,10 +218,10 @@ mod test {
use super::*; use super::*;
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use std::thread::spawn;
use proxmox_sys::fs::create_path; use proxmox_sys::fs::create_path;
use std::sync::atomic::AtomicU64;
use std::sync::Arc;
use std::thread::spawn;
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
@ -231,7 +232,6 @@ mod test {
} }
impl Init for TestData { impl Init for TestData {
fn initialize(this: &mut MaybeUninit<Self>) { fn initialize(this: &mut MaybeUninit<Self>) {
this.write(Self { this.write(Self {
count: 0, count: 0,
@ -264,11 +264,12 @@ mod test {
#[test] #[test]
fn test_shared_memory_mutex() -> Result<(), Error> { fn test_shared_memory_mutex() -> Result<(), Error> {
create_path("../target/testdata/", None, None)?; create_path("../target/testdata/", None, None)?;
let shared: SharedMemory<SingleMutexData> = let shared: SharedMemory<SingleMutexData> = SharedMemory::open(
SharedMemory::open(Path::new("../target/testdata/test1.shm"), CreateOptions::new())?; Path::new("../target/testdata/test1.shm"),
CreateOptions::new(),
)?;
let shared = Arc::new(shared); let shared = Arc::new(shared);
@ -292,7 +293,7 @@ mod test {
let end = shared.data().data.lock().count; let end = shared.data().data.lock().count;
assert_eq!(end-start, 100); assert_eq!(end - start, 100);
Ok(()) Ok(())
} }
@ -327,13 +328,14 @@ mod test {
#[test] #[test]
fn test_shared_memory_multi_mutex() -> Result<(), Error> { fn test_shared_memory_multi_mutex() -> Result<(), Error> {
create_path("../target/testdata/", None, None)?; create_path("../target/testdata/", None, None)?;
let shared: SharedMemory<MultiMutexData> = let shared: SharedMemory<MultiMutexData> = SharedMemory::open(
SharedMemory::open(Path::new("../target/testdata/test2.shm"), CreateOptions::new())?; Path::new("../target/testdata/test2.shm"),
CreateOptions::new(),
)?;
let shared = Arc::new(shared); let shared = Arc::new(shared);
let start1 = shared.data().block1.lock().count; let start1 = shared.data().block1.lock().count;
let start2 = shared.data().block2.lock().count; let start2 = shared.data().block2.lock().count;
@ -357,12 +359,11 @@ mod test {
} }
let end1 = shared.data().block1.lock().count; let end1 = shared.data().block1.lock().count;
assert_eq!(end1-start1, 100); assert_eq!(end1 - start1, 100);
let end2 = shared.data().block2.lock().count; let end2 = shared.data().block2.lock().count;
assert_eq!(end2-start2, 200); assert_eq!(end2 - start2, 200);
Ok(()) Ok(())
} }
} }

View File

@ -10,22 +10,32 @@ unsafe impl Send for RawSharedMutex {}
unsafe impl Sync for RawSharedMutex {} unsafe impl Sync for RawSharedMutex {}
impl RawSharedMutex { impl RawSharedMutex {
pub const fn uninitialized() -> Self { pub const fn uninitialized() -> Self {
Self { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } Self {
inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER),
}
} }
#[inline] #[inline]
pub unsafe fn init(&mut self) { pub unsafe fn init(&mut self) {
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit(); let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
let attr = PthreadMutexAttr(&mut attr); let attr = PthreadMutexAttr(&mut attr);
cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL)) cvt_nz(libc::pthread_mutexattr_settype(
.unwrap(); attr.0.as_mut_ptr(),
cvt_nz(libc::pthread_mutexattr_setpshared(attr.0.as_mut_ptr(), libc::PTHREAD_PROCESS_SHARED)) libc::PTHREAD_MUTEX_NORMAL,
.unwrap(); ))
cvt_nz(libc::pthread_mutexattr_setrobust(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_ROBUST)) .unwrap();
.unwrap(); cvt_nz(libc::pthread_mutexattr_setpshared(
attr.0.as_mut_ptr(),
libc::PTHREAD_PROCESS_SHARED,
))
.unwrap();
cvt_nz(libc::pthread_mutexattr_setrobust(
attr.0.as_mut_ptr(),
libc::PTHREAD_MUTEX_ROBUST,
))
.unwrap();
cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap(); cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
} }
@ -35,7 +45,7 @@ impl RawSharedMutex {
if r == libc::EOWNERDEAD { if r == libc::EOWNERDEAD {
r = libc::pthread_mutex_consistent(self.inner.get()); r = libc::pthread_mutex_consistent(self.inner.get());
} }
debug_assert_eq!(r, 0); debug_assert_eq!(r, 0);
} }
@ -56,7 +66,6 @@ impl RawSharedMutex {
} }
} }
// Note: copied from rust std::sys::unix::cvt_nz // Note: copied from rust std::sys::unix::cvt_nz
fn cvt_nz(error: libc::c_int) -> std::io::Result<()> { fn cvt_nz(error: libc::c_int) -> std::io::Result<()> {
if error == 0 { if error == 0 {

View File

@ -1,12 +1,12 @@
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::mem::MaybeUninit;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use anyhow::{bail, Error}; use anyhow::{bail, Error};
use crate::Init;
use crate::raw_shared_mutex::RawSharedMutex; use crate::raw_shared_mutex::RawSharedMutex;
use crate::Init;
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
@ -22,23 +22,23 @@ unsafe impl<T: ?Sized + Send> Sync for SharedMutex<T> {}
// openssl::sha::sha256(b"Proxmox SharedMutex v1.0")[0..8]; // openssl::sha::sha256(b"Proxmox SharedMutex v1.0")[0..8];
pub const PROXMOX_SHARED_MUTEX_MAGIC_1_0: [u8; 8] = [124, 229, 154, 62, 248, 0, 154, 55]; pub const PROXMOX_SHARED_MUTEX_MAGIC_1_0: [u8; 8] = [124, 229, 154, 62, 248, 0, 154, 55];
impl <T: Init> Init for SharedMutex<T> { impl<T: Init> Init for SharedMutex<T> {
fn initialize(this: &mut MaybeUninit<SharedMutex<T>>) { fn initialize(this: &mut MaybeUninit<SharedMutex<T>>) {
let me = unsafe { &mut *this.as_mut_ptr() }; let me = unsafe { &mut *this.as_mut_ptr() };
me.magic = PROXMOX_SHARED_MUTEX_MAGIC_1_0; me.magic = PROXMOX_SHARED_MUTEX_MAGIC_1_0;
me.inner = RawSharedMutex::uninitialized(); me.inner = RawSharedMutex::uninitialized();
unsafe { me.inner.init(); } unsafe {
me.inner.init();
}
let u: &mut MaybeUninit<T> = unsafe { std::mem::transmute(me.data.get_mut()) }; let u: &mut MaybeUninit<T> = unsafe { std::mem::transmute(me.data.get_mut()) };
Init::initialize(u); Init::initialize(u);
} }
fn check_type_magic(this: &MaybeUninit<Self>) -> Result<(), Error> { fn check_type_magic(this: &MaybeUninit<Self>) -> Result<(), Error> {
let me = unsafe { & *this.as_ptr() }; let me = unsafe { &*this.as_ptr() };
if me.magic != PROXMOX_SHARED_MUTEX_MAGIC_1_0 { if me.magic != PROXMOX_SHARED_MUTEX_MAGIC_1_0 {
bail!("SharedMutex: wrong magic number"); bail!("SharedMutex: wrong magic number");
} }
@ -47,9 +47,7 @@ impl <T: Init> Init for SharedMutex<T> {
} }
impl<T> SharedMutex<T> { impl<T> SharedMutex<T> {
pub fn lock(&self) -> SharedMutexGuard<'_, T> { pub fn lock(&self) -> SharedMutexGuard<'_, T> {
unsafe { unsafe {
self.inner.lock(); self.inner.lock();
SharedMutexGuard::new(self) SharedMutexGuard::new(self)
@ -69,7 +67,6 @@ impl<T> SharedMutex<T> {
pub fn unlock(guard: SharedMutexGuard<'_, T>) { pub fn unlock(guard: SharedMutexGuard<'_, T>) {
drop(guard); drop(guard);
} }
} }
pub struct SharedMutexGuard<'a, T: ?Sized + 'a> { pub struct SharedMutexGuard<'a, T: ?Sized + 'a> {