Line data Source code
1 : #include "fd_epoch.h" 2 : 3 : void * 4 0 : fd_epoch_new( void * shmem, ulong voter_max ) { 5 0 : if( FD_UNLIKELY( !shmem ) ) { 6 0 : FD_LOG_WARNING(( "NULL mem" )); 7 0 : return NULL; 8 0 : } 9 : 10 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_epoch_align() ) ) ) { 11 0 : FD_LOG_WARNING(( "misaligned mem" )); 12 0 : return NULL; 13 0 : } 14 : 15 0 : ulong footprint = fd_epoch_footprint( voter_max ); 16 0 : if( FD_UNLIKELY( !footprint ) ) { 17 0 : FD_LOG_WARNING(( "bad mem" )); 18 0 : return NULL; 19 0 : } 20 : 21 0 : fd_memset( shmem, 0, footprint ); 22 0 : fd_wksp_t * wksp = fd_wksp_containing( shmem ); 23 0 : if( FD_UNLIKELY( !wksp ) ) { 24 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" )); 25 0 : return NULL; 26 0 : } 27 : 28 0 : fd_memset( shmem, 0, footprint ); 29 0 : int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( voter_max ) ) + 2; /* fill ratio <= 0.25 */ 30 : 31 0 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 32 0 : fd_epoch_t * epoch = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_align(), sizeof(fd_epoch_t) ); 33 0 : void * epoch_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_voters_align(), fd_epoch_voters_footprint( lg_slot_cnt ) ); 34 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_epoch_align() ) == (ulong)shmem + footprint ); 35 : 36 0 : epoch->voters_gaddr = fd_wksp_gaddr_fast( wksp, fd_epoch_voters_join( fd_epoch_voters_new( epoch_voters, lg_slot_cnt ) ) ); 37 : 38 0 : epoch->epoch_gaddr = fd_wksp_gaddr_fast( wksp, epoch ); 39 0 : epoch->total_stake = 0UL; 40 0 : epoch->first_slot = FD_SLOT_NULL; 41 0 : epoch->last_slot = FD_SLOT_NULL; 42 : 43 0 : FD_COMPILER_MFENCE(); 44 0 : FD_VOLATILE( epoch->magic ) = FD_EPOCH_MAGIC; 45 0 : FD_COMPILER_MFENCE(); 46 : 47 0 : return shmem; 48 0 : } 49 : 50 : fd_epoch_t * 51 0 : fd_epoch_join( void * shepoch ) { 52 0 : fd_epoch_t * epoch = (fd_epoch_t *)shepoch; 53 : 54 0 : if( FD_UNLIKELY( !epoch ) ) { 55 0 : FD_LOG_WARNING(( "NULL epoch" )); 56 0 : return NULL; 57 0 : } 58 : 59 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)epoch, fd_epoch_align() ) ) ) { 60 0 : FD_LOG_WARNING(( "misaligned epoch" )); 61 0 : return NULL; 62 0 : } 63 : 64 0 : fd_wksp_t * wksp = fd_wksp_containing( epoch ); 65 0 : if( FD_UNLIKELY( !wksp ) ) { 66 0 : FD_LOG_WARNING(( "epoch must be part of a workspace" )); 67 0 : return NULL; 68 0 : } 69 : 70 0 : if( FD_UNLIKELY( epoch->magic!=FD_EPOCH_MAGIC ) ) { 71 0 : FD_LOG_WARNING(( "bad magic" )); 72 0 : return NULL; 73 0 : } 74 : 75 0 : return epoch; 76 0 : } 77 : 78 : void * 79 0 : fd_epoch_leave( fd_epoch_t const * epoch ) { 80 : 81 0 : if( FD_UNLIKELY( !epoch ) ) { 82 0 : FD_LOG_WARNING(( "NULL epoch" )); 83 0 : return NULL; 84 0 : } 85 : 86 0 : return (void *)epoch; 87 0 : } 88 : 89 : void * 90 0 : fd_epoch_delete( void * epoch ) { 91 : 92 0 : if( FD_UNLIKELY( !epoch ) ) { 93 0 : FD_LOG_WARNING(( "NULL epoch" )); 94 0 : return NULL; 95 0 : } 96 : 97 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)epoch, fd_epoch_align() ) ) ) { 98 0 : FD_LOG_WARNING(( "misaligned epoch" )); 99 0 : return NULL; 100 0 : } 101 : 102 0 : return epoch; 103 0 : } 104 : 105 : void 106 0 : fd_epoch_init( fd_epoch_t * epoch, fd_epoch_bank_t const * epoch_bank ) { 107 0 : epoch->first_slot = epoch_bank->eah_start_slot; 108 0 : epoch->last_slot = epoch_bank->eah_stop_slot; 109 : 110 0 : fd_voter_t * epoch_voters = fd_epoch_voters( epoch ); 111 0 : fd_vote_accounts_t const * vote_accounts = &epoch_bank->stakes.vote_accounts; 112 : 113 0 : for( fd_vote_accounts_pair_t_mapnode_t * curr = fd_vote_accounts_pair_t_map_minimum( 114 0 : vote_accounts->vote_accounts_pool, 115 0 : vote_accounts->vote_accounts_root ); 116 0 : curr; 117 0 : curr = fd_vote_accounts_pair_t_map_successor( vote_accounts->vote_accounts_pool, curr ) ) { 118 : 119 0 : if( FD_UNLIKELY( curr->elem.stake > 0UL ) ) { 120 : 121 0 : #if FD_EPOCH_USE_HANDHOLDING 122 0 : FD_TEST( !fd_epoch_voters_query( epoch_voters, curr->elem.key, NULL ) ); 123 0 : FD_TEST( fd_epoch_voters_key_cnt( epoch_voters ) < fd_epoch_voters_key_max( epoch_voters ) ); 124 0 : #endif 125 : 126 0 : fd_voter_t * voter = fd_epoch_voters_insert( epoch_voters, curr->elem.key ); 127 0 : voter->rec.c[FD_FUNK_REC_KEY_FOOTPRINT - 1] = FD_FUNK_KEY_TYPE_ACC; 128 : 129 0 : #if FD_EPOCH_USE_HANDHOLDING 130 0 : FD_TEST( 0 == memcmp( &voter->key, &curr->elem.key, sizeof(fd_pubkey_t) ) ); 131 0 : FD_TEST( fd_epoch_voters_query( epoch_voters, voter->key, NULL ) ); 132 0 : #endif 133 : 134 0 : voter->stake = curr->elem.stake; 135 : 136 0 : voter->replay_vote = FD_SLOT_NULL; 137 0 : voter->gossip_vote = FD_SLOT_NULL; 138 0 : voter->rooted_vote = FD_SLOT_NULL; 139 0 : } 140 0 : epoch->total_stake += curr->elem.stake; 141 0 : } 142 0 : } 143 : 144 : void 145 0 : fd_epoch_fini( fd_epoch_t * epoch ) { 146 0 : fd_epoch_voters_clear( fd_epoch_voters( epoch ) ); 147 0 : epoch->total_stake = 0UL; 148 0 : }