LCOV - code coverage report
Current view: top level - libs/neon-shmem/src - sync.rs (source / functions) Coverage Total Hit
Test: 4be46b1c0003aa3bbac9ade362c676b419df4c20.info Lines: 59.5 % 42 25
Test Date: 2025-07-22 17:50:06 Functions: 75.0 % 8 6

            Line data    Source code
       1              : //! Simple utilities akin to what's in [`std::sync`] but designed to work with shared memory.
       2              : 
       3              : use std::mem::MaybeUninit;
       4              : use std::ptr::NonNull;
       5              : 
       6              : use nix::errno::Errno;
       7              : 
       8              : pub type RwLock<T> = lock_api::RwLock<PthreadRwLock, T>;
       9              : pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, PthreadRwLock, T>;
      10              : pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, PthreadRwLock, T>;
      11              : pub type ValueReadGuard<'a, T> = lock_api::MappedRwLockReadGuard<'a, PthreadRwLock, T>;
      12              : pub type ValueWriteGuard<'a, T> = lock_api::MappedRwLockWriteGuard<'a, PthreadRwLock, T>;
      13              : 
      14              : /// Shared memory read-write lock.
      15              : pub struct PthreadRwLock(Option<NonNull<libc::pthread_rwlock_t>>);
      16              : 
      17              : /// Simple macro that calls a function in the libc namespace and panics if return value is nonzero.
      18              : macro_rules! libc_checked {
      19              :     ($fn_name:ident ( $($arg:expr),* )) => {{
      20              :         let res = libc::$fn_name($($arg),*);
      21              :         if res != 0 {
      22              :             panic!("{} failed with {}", stringify!($fn_name), Errno::from_raw(res));
      23              :         }
      24              :     }};
      25              : }
      26              : 
      27              : impl PthreadRwLock {
      28              :     /// Creates a new `PthreadRwLock` on top of a pointer to a pthread rwlock.
      29              :     ///
      30              :     /// # Safety
      31              :     /// `lock` must be non-null. Every unsafe operation will panic in the event of an error.
      32           26 :     pub unsafe fn new(lock: *mut libc::pthread_rwlock_t) -> Self {
      33              :         unsafe {
      34           26 :             let mut attrs = MaybeUninit::uninit();
      35           26 :             libc_checked!(pthread_rwlockattr_init(attrs.as_mut_ptr()));
      36           26 :             libc_checked!(pthread_rwlockattr_setpshared(
      37           26 :                 attrs.as_mut_ptr(),
      38              :                 libc::PTHREAD_PROCESS_SHARED
      39              :             ));
      40           26 :             libc_checked!(pthread_rwlock_init(lock, attrs.as_mut_ptr()));
      41              :             // Safety: POSIX specifies that "any function affecting the attributes
      42              :             // object (including destruction) shall not affect any previously
      43              :             // initialized read-write locks".
      44           26 :             libc_checked!(pthread_rwlockattr_destroy(attrs.as_mut_ptr()));
      45           26 :             Self(Some(NonNull::new_unchecked(lock)))
      46              :         }
      47           26 :     }
      48              : 
      49       810972 :     fn inner(&self) -> NonNull<libc::pthread_rwlock_t> {
      50       810972 :         match self.0 {
      51              :             None => {
      52            0 :                 panic!("PthreadRwLock constructed badly - something likely used RawRwLock::INIT")
      53              :             }
      54       810972 :             Some(x) => x,
      55              :         }
      56       810972 :     }
      57              : }
      58              : 
      59              : unsafe impl lock_api::RawRwLock for PthreadRwLock {
      60              :     type GuardMarker = lock_api::GuardSend;
      61              :     const INIT: Self = Self(None);
      62              : 
      63            0 :     fn try_lock_shared(&self) -> bool {
      64              :         unsafe {
      65            0 :             let res = libc::pthread_rwlock_tryrdlock(self.inner().as_ptr());
      66            0 :             match res {
      67            0 :                 0 => true,
      68            0 :                 libc::EAGAIN => false,
      69            0 :                 _ => panic!(
      70            0 :                     "pthread_rwlock_tryrdlock failed with {}",
      71            0 :                     Errno::from_raw(res)
      72              :                 ),
      73              :             }
      74              :         }
      75            0 :     }
      76              : 
      77            0 :     fn try_lock_exclusive(&self) -> bool {
      78              :         unsafe {
      79            0 :             let res = libc::pthread_rwlock_trywrlock(self.inner().as_ptr());
      80            0 :             match res {
      81            0 :                 0 => true,
      82            0 :                 libc::EAGAIN => false,
      83            0 :                 _ => panic!("try_wrlock failed with {}", Errno::from_raw(res)),
      84              :             }
      85              :         }
      86            0 :     }
      87              : 
      88       111259 :     fn lock_shared(&self) {
      89              :         unsafe {
      90       111259 :             libc_checked!(pthread_rwlock_rdlock(self.inner().as_ptr()));
      91              :         }
      92       111259 :     }
      93              : 
      94       294227 :     fn lock_exclusive(&self) {
      95              :         unsafe {
      96       294227 :             libc_checked!(pthread_rwlock_wrlock(self.inner().as_ptr()));
      97              :         }
      98       294227 :     }
      99              : 
     100       294227 :     unsafe fn unlock_exclusive(&self) {
     101              :         unsafe {
     102       294227 :             libc_checked!(pthread_rwlock_unlock(self.inner().as_ptr()));
     103              :         }
     104       294227 :     }
     105              : 
     106       111259 :     unsafe fn unlock_shared(&self) {
     107              :         unsafe {
     108       111259 :             libc_checked!(pthread_rwlock_unlock(self.inner().as_ptr()));
     109              :         }
     110       111259 :     }
     111              : }
        

Generated by: LCOV version 2.1-beta