Line data Source code
1 : #include "fd_acc_pool.h" 2 : #include "fd_runtime_const.h" 3 : #include "../fd_rwlock.h" 4 : 5 723 : #define FD_ACC_POOL_MAGIC (0xF17EDA2CEACC6001UL) /* FIREDANCE ACC POOL */ 6 : 7 : struct fd_acc_entry { 8 : uchar account[ sizeof(fd_account_meta_t) + FD_RUNTIME_ACC_SZ_MAX ] __attribute__((aligned(FD_ACCOUNT_REC_ALIGN))); 9 : ulong magic; 10 : ulong next_; 11 : }; 12 : typedef struct fd_acc_entry fd_acc_entry_t; 13 : 14 : #define POOL_NAME fd_acc_entry_pool 15 417 : #define POOL_T fd_acc_entry_t 16 1212 : #define POOL_NEXT next_ 17 : #include "../../util/tmpl/fd_pool.c" 18 : 19 : struct fd_acc_pool { 20 : fd_rwlock_t lock_; 21 : ulong pool_offset; 22 : ulong magic; 23 : }; 24 : typedef struct fd_acc_pool fd_acc_pool_t; 25 : 26 : static inline fd_acc_entry_t * 27 363 : fd_acc_pool( fd_acc_pool_t * acc_pool ) { 28 363 : return fd_acc_entry_pool_join( (uchar *)acc_pool + acc_pool->pool_offset ); 29 363 : } 30 : 31 : ulong 32 270 : fd_acc_pool_align( void ) { 33 270 : return 128UL; 34 270 : } 35 : 36 : ulong 37 27 : fd_acc_pool_footprint( ulong account_cnt ) { 38 : 39 27 : ulong l = FD_LAYOUT_INIT; 40 27 : l = FD_LAYOUT_APPEND( l, fd_acc_pool_align(), sizeof(fd_acc_pool_t) ); 41 27 : l = FD_LAYOUT_APPEND( l, fd_acc_entry_pool_align(), fd_acc_entry_pool_footprint( account_cnt ) ); 42 27 : return FD_LAYOUT_FINI( l, fd_acc_pool_align() ); 43 27 : } 44 : 45 : void * 46 : fd_acc_pool_new( void * shmem, 47 27 : ulong account_cnt ) { 48 27 : if( FD_UNLIKELY( !shmem ) ) { 49 0 : FD_LOG_WARNING(( "NULL shmem" )); 50 0 : return NULL; 51 0 : } 52 : 53 27 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_acc_pool_align() ) ) ) { 54 0 : FD_LOG_WARNING(( "misaligned shmem" )); 55 0 : return NULL; 56 0 : } 57 : 58 27 : if( FD_UNLIKELY( account_cnt==0UL ) ) { 59 0 : FD_LOG_WARNING(( "account_cnt is 0" )); 60 0 : return NULL; 61 0 : } 62 : 63 27 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 64 27 : fd_acc_pool_t * acc_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_acc_pool_align(), sizeof(fd_acc_pool_t) ); 65 27 : void * pool = FD_SCRATCH_ALLOC_APPEND( l, fd_acc_entry_pool_align(), fd_acc_entry_pool_footprint( account_cnt ) ); 66 27 : FD_SCRATCH_ALLOC_FINI( l, fd_acc_pool_align() ); 67 : 68 27 : fd_acc_entry_t * fd_acc_entry_pool = fd_acc_entry_pool_join( fd_acc_entry_pool_new( pool, account_cnt ) ); 69 27 : if( FD_UNLIKELY( !fd_acc_entry_pool ) ) { 70 0 : FD_LOG_WARNING(( "Failed to create acc pool" )); 71 0 : return NULL; 72 0 : } 73 : 74 27 : acc_pool->pool_offset = (ulong)pool-(ulong)acc_pool; 75 : 76 27 : fd_rwlock_new( &acc_pool->lock_ ); 77 : 78 27 : FD_COMPILER_MFENCE(); 79 27 : FD_VOLATILE( acc_pool->magic ) = FD_ACC_POOL_MAGIC; 80 723 : for( ulong i=0UL; i<account_cnt; i++ ) { 81 696 : fd_acc_entry_t * ele = fd_acc_entry_pool_ele( fd_acc_entry_pool, i ); 82 696 : ele->magic = FD_ACC_POOL_MAGIC; 83 696 : } 84 27 : FD_COMPILER_MFENCE(); 85 : 86 27 : return shmem; 87 27 : } 88 : 89 : 90 : fd_acc_pool_t * 91 27 : fd_acc_pool_join( void * mem ) { 92 : 93 27 : fd_acc_pool_t * acc_pool = (fd_acc_pool_t *)mem; 94 : 95 27 : if( FD_UNLIKELY( !mem ) ) { 96 0 : FD_LOG_WARNING(( "NULL mem" )); 97 0 : return NULL; 98 0 : } 99 : 100 27 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_acc_pool_align() ) ) ) { 101 0 : FD_LOG_WARNING(( "misaligned mem" )); 102 0 : return NULL; 103 0 : } 104 : 105 27 : fd_acc_entry_t * fd_acc_entry_pool = fd_acc_pool( acc_pool ); 106 27 : if( FD_UNLIKELY( !fd_acc_entry_pool ) ) { 107 0 : FD_LOG_WARNING(( "Failed to join acc entry pool" )); 108 0 : return NULL; 109 0 : } 110 : 111 723 : for( ulong i=0UL; i<fd_acc_entry_pool_max( fd_acc_entry_pool ); i++ ) { 112 696 : fd_acc_entry_t * ele = fd_acc_entry_pool_ele( fd_acc_entry_pool, i ); 113 696 : if( FD_UNLIKELY( ele->magic!=FD_ACC_POOL_MAGIC ) ) { 114 0 : FD_LOG_WARNING(( "Invalid acc entry magic" )); 115 0 : return NULL; 116 0 : } 117 696 : } 118 : 119 27 : if( FD_UNLIKELY( acc_pool->magic!=FD_ACC_POOL_MAGIC ) ) { 120 0 : FD_LOG_WARNING(( "Invalid acc pool magic" )); 121 0 : return NULL; 122 0 : } 123 : 124 27 : return acc_pool; 125 27 : } 126 : 127 : int 128 : fd_acc_pool_try_acquire( fd_acc_pool_t * acc_pool, 129 : ulong request_cnt, 130 66 : uchar * * accounts_out ) { 131 66 : fd_rwlock_write( &acc_pool->lock_ ); 132 : 133 66 : fd_acc_entry_t * pool = fd_acc_pool( acc_pool ); 134 : 135 66 : if( FD_UNLIKELY( fd_acc_entry_pool_free( pool )<request_cnt ) ) { 136 0 : fd_rwlock_unwrite( &acc_pool->lock_ ); 137 0 : return 1; 138 0 : } 139 : 140 333 : for( ulong i=0UL; i<request_cnt; i++ ) { 141 267 : fd_acc_entry_t * ele = fd_acc_entry_pool_ele_acquire( pool ); 142 267 : accounts_out[ i ] = (uchar *)ele; 143 267 : } 144 : 145 66 : fd_rwlock_unwrite( &acc_pool->lock_ ); 146 : 147 66 : return 0; 148 66 : } 149 : 150 : void 151 : fd_acc_pool_acquire( fd_acc_pool_t * acc_pool, 152 : ulong request_cnt, 153 66 : uchar * * accounts_out ) { 154 66 : for( ;; ) { 155 66 : int err = fd_acc_pool_try_acquire( acc_pool, request_cnt, accounts_out ); 156 66 : if( FD_LIKELY( err==0 ) ) break; 157 66 : } 158 66 : } 159 : 160 : void 161 : fd_acc_pool_release( fd_acc_pool_t * acc_pool, 162 249 : uchar * account ) { 163 249 : fd_rwlock_write( &acc_pool->lock_ ); 164 : 165 249 : fd_acc_entry_t * pool = fd_acc_pool( acc_pool ); 166 : 167 249 : fd_acc_entry_t * ele = fd_type_pun( account ); 168 249 : fd_acc_entry_pool_ele_release( pool, ele ); 169 : 170 249 : fd_rwlock_unwrite( &acc_pool->lock_ ); 171 249 : } 172 : 173 : ulong 174 21 : fd_acc_pool_free( fd_acc_pool_t * acc_pool ) { 175 21 : fd_rwlock_read( &acc_pool->lock_ ); 176 21 : ulong free = fd_acc_entry_pool_free( fd_acc_pool( acc_pool ) ); 177 21 : fd_rwlock_unread( &acc_pool->lock_ ); 178 21 : return free; 179 21 : }