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 : 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 fd_rwlock_t * 19 1577394 : fd_rwlock_new( fd_rwlock_t * lock ) { 20 1577394 : lock->value = 0; 21 1577394 : return 0; 22 1577394 : } 23 : 24 : static inline void 25 572610 : fd_rwlock_write( fd_rwlock_t * lock ) { 26 572610 : # if FD_HAS_THREADS 27 572610 : for(;;) { 28 572610 : ushort value = lock->value; 29 572610 : if( FD_LIKELY( !value ) ) { 30 572610 : if( FD_LIKELY( FD_ATOMIC_CAS( &lock->value, 0, 0xFFFF )==0 ) ) return; 31 572610 : } 32 0 : FD_SPIN_PAUSE(); 33 0 : } 34 : # else 35 : lock->value = 0xFFFF; 36 : # endif 37 0 : FD_COMPILER_MFENCE(); 38 0 : } 39 : 40 : static inline void 41 573222 : fd_rwlock_unwrite( fd_rwlock_t * lock ) { 42 573222 : FD_COMPILER_MFENCE(); 43 573222 : lock->value = 0; 44 573222 : } 45 : 46 : static inline void 47 45 : fd_rwlock_read( fd_rwlock_t * lock ) { 48 45 : # if FD_HAS_THREADS 49 45 : for(;;) { 50 45 : ushort value = lock->value; 51 45 : if( FD_UNLIKELY( value<0xFFFE ) ) { 52 45 : if( FD_LIKELY( FD_ATOMIC_CAS( &lock->value, value, value+1 )==value ) ) { 53 45 : return; 54 45 : } 55 45 : } 56 0 : FD_SPIN_PAUSE(); 57 0 : } 58 : # else 59 : lock->value++; 60 : # endif 61 0 : FD_COMPILER_MFENCE(); 62 0 : } 63 : 64 : static inline void 65 105 : fd_rwlock_unread( fd_rwlock_t * lock ) { 66 105 : FD_COMPILER_MFENCE(); 67 105 : # if FD_HAS_THREADS 68 105 : FD_ATOMIC_FETCH_AND_SUB( &lock->value, 1 ); 69 : # else 70 : lock->value--; 71 : # endif 72 105 : } 73 : 74 : #endif /* HEADER_fd_src_flamenco_fd_rwlock_h */