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