Line data Source code
1 : #include "fd_acc_pool.h" 2 : #include "fd_runtime_const.h" 3 : #include "../fd_rwlock.h" 4 : 5 1248 : #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 555 : #define POOL_T fd_acc_entry_t 16 1836 : #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 459 : fd_acc_pool( fd_acc_pool_t * acc_pool ) { 28 459 : return fd_acc_entry_pool_join( (uchar *)acc_pool + acc_pool->pool_offset ); 29 459 : } 30 : 31 : ulong 32 480 : fd_acc_pool_align( void ) { 33 480 : return 128UL; 34 480 : } 35 : 36 : ulong 37 48 : fd_acc_pool_footprint( ulong account_cnt ) { 38 : 39 48 : ulong l = FD_LAYOUT_INIT; 40 48 : l = FD_LAYOUT_APPEND( l, fd_acc_pool_align(), sizeof(fd_acc_pool_t) ); 41 48 : l = FD_LAYOUT_APPEND( l, fd_acc_entry_pool_align(), fd_acc_entry_pool_footprint( account_cnt ) ); 42 48 : return FD_LAYOUT_FINI( l, fd_acc_pool_align() ); 43 48 : } 44 : 45 : void * 46 : fd_acc_pool_new( void * shmem, 47 48 : ulong account_cnt ) { 48 48 : if( FD_UNLIKELY( !shmem ) ) { 49 0 : FD_LOG_WARNING(( "NULL shmem" )); 50 0 : return NULL; 51 0 : } 52 : 53 48 : 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 48 : if( FD_UNLIKELY( account_cnt==0UL ) ) { 59 0 : FD_LOG_WARNING(( "account_cnt is 0" )); 60 0 : return NULL; 61 0 : } 62 : 63 48 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 64 48 : fd_acc_pool_t * acc_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_acc_pool_align(), sizeof(fd_acc_pool_t) ); 65 48 : void * pool = FD_SCRATCH_ALLOC_APPEND( l, fd_acc_entry_pool_align(), fd_acc_entry_pool_footprint( account_cnt ) ); 66 48 : FD_SCRATCH_ALLOC_FINI( l, fd_acc_pool_align() ); 67 : 68 48 : fd_acc_entry_t * fd_acc_entry_pool = fd_acc_entry_pool_join( fd_acc_entry_pool_new( pool, account_cnt ) ); 69 48 : 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 48 : acc_pool->pool_offset = (ulong)pool-(ulong)acc_pool; 75 : 76 48 : fd_rwlock_new( &acc_pool->lock_ ); 77 : 78 48 : FD_COMPILER_MFENCE(); 79 48 : FD_VOLATILE( acc_pool->magic ) = FD_ACC_POOL_MAGIC; 80 1248 : for( ulong i=0UL; i<account_cnt; i++ ) { 81 1200 : fd_acc_entry_t * ele = fd_acc_entry_pool_ele( fd_acc_entry_pool, i ); 82 1200 : ele->magic = FD_ACC_POOL_MAGIC; 83 1200 : } 84 48 : FD_COMPILER_MFENCE(); 85 : 86 48 : return shmem; 87 48 : } 88 : 89 : 90 : fd_acc_pool_t * 91 48 : fd_acc_pool_join( void * mem ) { 92 : 93 48 : fd_acc_pool_t * acc_pool = (fd_acc_pool_t *)mem; 94 : 95 48 : if( FD_UNLIKELY( !mem ) ) { 96 0 : FD_LOG_WARNING(( "NULL mem" )); 97 0 : return NULL; 98 0 : } 99 : 100 48 : 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 48 : fd_acc_entry_t * fd_acc_entry_pool = fd_acc_pool( acc_pool ); 106 48 : 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 1248 : for( ulong i=0UL; i<fd_acc_entry_pool_max( fd_acc_entry_pool ); i++ ) { 112 1200 : fd_acc_entry_t * ele = fd_acc_entry_pool_ele( fd_acc_entry_pool, i ); 113 1200 : 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 1200 : } 118 : 119 48 : 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 48 : return acc_pool; 125 48 : } 126 : 127 : int 128 : fd_acc_pool_try_acquire( fd_acc_pool_t * acc_pool, 129 : ulong request_cnt, 130 81 : uchar * * accounts_out ) { 131 81 : fd_rwlock_write( &acc_pool->lock_ ); 132 : 133 81 : fd_acc_entry_t * pool = fd_acc_pool( acc_pool ); 134 : 135 81 : 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 408 : for( ulong i=0UL; i<request_cnt; i++ ) { 141 327 : fd_acc_entry_t * ele = fd_acc_entry_pool_ele_acquire( pool ); 142 327 : accounts_out[ i ] = (uchar *)ele; 143 327 : } 144 : 145 81 : fd_rwlock_unwrite( &acc_pool->lock_ ); 146 : 147 81 : return 0; 148 81 : } 149 : 150 : void 151 : fd_acc_pool_acquire( fd_acc_pool_t * acc_pool, 152 : ulong request_cnt, 153 81 : uchar * * accounts_out ) { 154 81 : for( ;; ) { 155 81 : int err = fd_acc_pool_try_acquire( acc_pool, request_cnt, accounts_out ); 156 81 : if( FD_LIKELY( err==0 ) ) break; 157 81 : } 158 81 : } 159 : 160 : void 161 : fd_acc_pool_release( fd_acc_pool_t * acc_pool, 162 309 : uchar * account ) { 163 309 : fd_rwlock_write( &acc_pool->lock_ ); 164 : 165 309 : fd_acc_entry_t * pool = fd_acc_pool( acc_pool ); 166 : 167 309 : fd_acc_entry_t * ele = fd_type_pun( account ); 168 309 : fd_acc_entry_pool_ele_release( pool, ele ); 169 : 170 309 : fd_rwlock_unwrite( &acc_pool->lock_ ); 171 309 : } 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 : }