Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_fd_rwseq_lock_h 2 : #define HEADER_fd_src_flamenco_runtime_fd_rwseq_lock_h 3 : 4 : #include "../fd_flamenco_base.h" 5 : #include "../fd_rwlock.h" 6 : 7 : struct __attribute__((aligned(64UL))) fd_rwseq_lock { 8 : fd_rwlock_t rwlock; 9 : volatile uint seqnum; 10 : }; 11 : 12 : typedef struct fd_rwseq_lock fd_rwseq_lock_t; 13 : 14 : static inline FD_FN_CONST ulong 15 0 : fd_rwseq_align( void ) { return alignof(fd_rwseq_lock_t); } 16 : 17 : static inline FD_FN_CONST ulong 18 0 : fd_rwseq_footprint( void ) { return sizeof(fd_rwseq_lock_t); } 19 : 20 : static inline void * 21 0 : fd_rwseq_new( void * shmem ) { 22 0 : fd_rwseq_lock_t * lock = (fd_rwseq_lock_t *)shmem; 23 0 : lock->rwlock.value = 0; 24 0 : lock->seqnum = 0; 25 0 : return lock; 26 0 : } 27 : 28 : static inline fd_rwseq_lock_t * 29 0 : fd_rwseq_join( void * shrwseq ) { 30 0 : return (fd_rwseq_lock_t *)shrwseq; 31 0 : } 32 : 33 : static inline void * 34 0 : fd_rwseq_leave( fd_rwseq_lock_t * lock ) { 35 0 : return lock; 36 0 : } 37 : 38 : static inline void * 39 0 : fd_rwseq_delete( void * shrwseq ) { 40 0 : return shrwseq; 41 0 : } 42 : 43 : static inline void 44 0 : fd_rwseq_start_read( fd_rwseq_lock_t * lock ) { 45 0 : fd_rwlock_read( &lock->rwlock ); 46 0 : } 47 : 48 : static inline void 49 0 : fd_rwseq_end_read( fd_rwseq_lock_t * lock ) { 50 0 : fd_rwlock_unread( &lock->rwlock ); 51 0 : } 52 : 53 : static inline void 54 0 : fd_rwseq_start_write( fd_rwseq_lock_t * lock ) { 55 0 : fd_rwlock_write( &lock->rwlock ); 56 0 : FD_COMPILER_MFENCE(); 57 0 : lock->seqnum++; 58 0 : FD_COMPILER_MFENCE(); 59 0 : } 60 : 61 : static inline void 62 0 : fd_rwseq_end_write( fd_rwseq_lock_t * lock ) { 63 0 : FD_COMPILER_MFENCE(); 64 0 : lock->seqnum++; 65 0 : FD_COMPILER_MFENCE(); 66 0 : fd_rwlock_unwrite( &lock->rwlock ); 67 0 : } 68 : 69 : /* The pattern for concurrent reads is: 70 : for(;;) { 71 : uint seqnum; 72 : if( FD_UNLIKELY( fd_rwseq_start_concur_read( lock, &seqnum ) ) ) continue; 73 : ... read some data 74 : if( FD_UNLIKELY( fd_rwseq_check_concur_read( lock, seqnum ) ) ) continue; 75 : return; 76 : } 77 : */ 78 : 79 : static inline int 80 0 : fd_rwseq_start_concur_read( fd_rwseq_lock_t * lock, uint * seqnum ) { 81 0 : *seqnum = lock->seqnum; 82 0 : FD_COMPILER_MFENCE(); 83 0 : return ( lock->rwlock.value==0xFFFF ? 1 : 0 ); 84 0 : } 85 : 86 : static inline int 87 0 : fd_rwseq_check_concur_read( fd_rwseq_lock_t * lock, uint seqnum ) { 88 0 : FD_COMPILER_MFENCE(); 89 0 : return ( (int)(seqnum != lock->seqnum) | (int)( lock->rwlock.value==0xFFFF ? 1 : 0 ) ); 90 0 : } 91 : 92 : #endif /* HEADER_fd_src_flamenco_runtime_fd_rwseq_lock_h */