LCOV - code coverage report
Current view: top level - flamenco - fd_rwlock.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 51 57 89.5 %
Date: 2026-03-19 18:19:27 Functions: 32 1768 1.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_fd_rwlock_h
       2             : #define HEADER_fd_src_flamenco_fd_rwlock_h
       3             : 
       4             : /* A very simple read-write spin lock. */
       5             : 
       6             : #include "../util/fd_util_base.h"
       7             : #include "../util/sanitize/fd_tsa.h"
       8             : 
       9             : #define FD_RWLOCK_WRITE_LOCK ((ushort)0xFFFF)
      10             : 
      11             : struct FD_CAPABILITY("fd_rwlock") fd_rwlock {
      12             :   ushort value; /* Bits 0..16 are
      13             : 
      14             :                     0: Unlocked
      15             :                     1..=0xFFFE: Locked by N readers
      16             :                     0xFFFF: Write locked */
      17             : };
      18             : 
      19             : typedef struct fd_rwlock fd_rwlock_t;
      20             : 
      21             : static inline fd_rwlock_t *
      22      110904 : fd_rwlock_new( fd_rwlock_t * lock ) FD_NO_THREAD_SAFETY_ANALYSIS {
      23      110904 :   lock->value = 0;
      24      110904 :   return lock;
      25      110904 : }
      26             : 
      27             : static inline void
      28       87486 : fd_rwlock_write( fd_rwlock_t * lock ) FD_ACQUIRE( lock )  FD_NO_THREAD_SAFETY_ANALYSIS {
      29       87486 : # if FD_HAS_THREADS
      30       87486 :   for(;;) {
      31       87486 :     ushort value = lock->value;
      32       87486 :     if( FD_LIKELY( !value ) ) {
      33       87505 :       if( FD_LIKELY( FD_ATOMIC_CAS( &lock->value, 0, 0xFFFF )==0 ) ) {
      34       87505 :         FD_COMPILER_MFENCE();
      35       87505 :         return;
      36       87505 :       }
      37       87483 :     }
      38 >1844*10^16 :     FD_SPIN_PAUSE();
      39 >1844*10^16 :   }
      40             : # else
      41             :   lock->value = 0xFFFF;
      42             :   FD_COMPILER_MFENCE();
      43             : # endif
      44       87486 : }
      45             : 
      46             : static inline void
      47      116247 : fd_rwlock_unwrite( fd_rwlock_t * lock ) FD_RELEASE( lock ) FD_NO_THREAD_SAFETY_ANALYSIS {
      48      116247 :   FD_COMPILER_MFENCE();
      49      116247 :   FD_VOLATILE( lock->value ) = 0;
      50      116247 : }
      51             : 
      52             : static inline void
      53        1404 : fd_rwlock_demote( fd_rwlock_t * lock ) FD_RELEASE( lock ) FD_ACQUIRE_SHARED( lock ) FD_NO_THREAD_SAFETY_ANALYSIS {
      54        1404 :   FD_COMPILER_MFENCE();
      55        1404 :   FD_VOLATILE( lock->value ) = 1;
      56        1404 : }
      57             : 
      58             : static inline void
      59       47412 : fd_rwlock_read( fd_rwlock_t * lock ) FD_ACQUIRE_SHARED( lock ) FD_NO_THREAD_SAFETY_ANALYSIS  {
      60       47412 : # if FD_HAS_THREADS
      61       47412 :   for(;;) {
      62       47411 :     ushort value = lock->value;
      63       47412 :     if( FD_LIKELY( value<0xFFFE ) ) {
      64       47425 :       if( FD_LIKELY( FD_ATOMIC_CAS( &lock->value, value, value+1 )==value ) ) {
      65       47425 :         FD_COMPILER_MFENCE();
      66       47425 :         return;
      67       47425 :       }
      68       47412 :     }
      69 >1844*10^16 :     FD_SPIN_PAUSE();
      70 >1844*10^16 :   }
      71             : # else
      72             :   lock->value++;
      73             :   FD_COMPILER_MFENCE();
      74             : # endif
      75       47412 : }
      76             : 
      77             : /* fd_rwlock_tryread attempts to acquire a shared read lock without
      78             :    spinning.  Returns 1 on success, 0 on failure (lock is write-held
      79             :    or contended). */
      80             : 
      81             : static inline int
      82        5400 : fd_rwlock_tryread( fd_rwlock_t * lock ) FD_TRY_ACQUIRE_SHARED(1, lock) FD_NO_THREAD_SAFETY_ANALYSIS {
      83        5400 : # if FD_HAS_THREADS
      84        5400 :   ushort value = lock->value;
      85        5400 :   if( FD_UNLIKELY( value>=0xFFFE ) ) return 0;
      86        5400 :   if( FD_UNLIKELY( FD_ATOMIC_CAS( &lock->value, value, (ushort)(value+1) )!=value ) ) return 0;
      87        5400 :   FD_COMPILER_MFENCE();
      88        5400 :   return 1;
      89             : # else
      90             :   lock->value++;
      91             :   FD_COMPILER_MFENCE();
      92             :   return 1;
      93             : # endif
      94        5400 : }
      95             : 
      96             : static inline int
      97           0 : fd_rwlock_trywrite( fd_rwlock_t * lock ) FD_TRY_ACQUIRE(1, lock) FD_NO_THREAD_SAFETY_ANALYSIS {
      98           0 : # if FD_HAS_THREADS
      99           0 :   if( FD_UNLIKELY( FD_ATOMIC_CAS( &lock->value, 0, FD_RWLOCK_WRITE_LOCK )!=0 ) ) return 0;
     100           0 :   FD_COMPILER_MFENCE();
     101           0 :   return 1;
     102             : # else
     103             :   if( FD_UNLIKELY( lock->value ) ) return 0;
     104             :   lock->value = FD_RWLOCK_WRITE_LOCK;
     105             :   FD_COMPILER_MFENCE();
     106             :   return 1;
     107             : # endif
     108           0 : }
     109             : 
     110             : static inline void
     111       54185 : fd_rwlock_unread( fd_rwlock_t * lock ) FD_RELEASE_SHARED( lock ) FD_NO_THREAD_SAFETY_ANALYSIS {
     112       54185 :   FD_COMPILER_MFENCE();
     113       54185 : # if FD_HAS_THREADS
     114       54185 :   FD_ATOMIC_FETCH_AND_SUB( &lock->value, 1 );
     115             : # else
     116             :   lock->value--;
     117             : # endif
     118       54185 : }
     119             : 
     120             : #endif /* HEADER_fd_src_flamenco_fd_rwlock_h */

Generated by: LCOV version 1.14