Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_rwlock_h 2 : #define HEADER_fd_src_flamenco_rwlock_h 3 : 4 : /* A very simple read-write spin lock. */ 5 : 6 : #include "../util/fd_util_base.h" 7 : 8 : struct fd_rwlock { 9 : ushort value; /* Bits 0..16 are 10 : 11 : 0: Unlocked 12 : 1..=0xFFFE: Locked by N readers 13 : 0xFFFF: Write locked */ 14 : }; 15 : 16 : typedef struct fd_rwlock fd_rwlock_t; 17 : 18 : static inline void 19 1570863 : fd_rwlock_write( fd_rwlock_t * lock ) { 20 1570863 : # if FD_HAS_THREADS 21 1570863 : for(;;) { 22 1570863 : ushort value = lock->value; 23 1570863 : if( FD_LIKELY( !value ) ) { 24 1570863 : if( FD_LIKELY( FD_ATOMIC_CAS( &lock->value, 0, 0xFFFF )==0 ) ) return; 25 1570863 : } 26 0 : FD_SPIN_PAUSE(); 27 0 : } 28 : # else 29 : lock->value = 0xFFFF; 30 : # endif 31 0 : FD_COMPILER_MFENCE(); 32 0 : } 33 : 34 : static inline void 35 1570863 : fd_rwlock_unwrite( fd_rwlock_t * lock ) { 36 1570863 : FD_COMPILER_MFENCE(); 37 1570863 : lock->value = 0; 38 1570863 : } 39 : 40 : static inline void 41 0 : fd_rwlock_read( fd_rwlock_t * lock ) { 42 0 : # if FD_HAS_THREADS 43 0 : for(;;) { 44 0 : ushort value = lock->value; 45 0 : if( FD_UNLIKELY( value<0xFFFE ) ) { 46 0 : if( FD_LIKELY( FD_ATOMIC_CAS( &lock->value, value, value+1 )==value ) ) { 47 0 : return; 48 0 : } 49 0 : } 50 0 : FD_SPIN_PAUSE(); 51 0 : } 52 : # else 53 : lock->value++; 54 : # endif 55 0 : FD_COMPILER_MFENCE(); 56 0 : } 57 : 58 : static inline void 59 0 : fd_rwlock_unread( fd_rwlock_t * lock ) { 60 0 : FD_COMPILER_MFENCE(); 61 0 : # if FD_HAS_THREADS 62 0 : FD_ATOMIC_FETCH_AND_SUB( &lock->value, 1 ); 63 : # else 64 : lock->value--; 65 : # endif 66 0 : } 67 : 68 : #endif /* HEADER_fd_src_flamenco_rwlock_h */