Line data Source code
1 : #include "fd_epoch_forks.h" 2 : #include "../../flamenco/runtime/context/fd_exec_epoch_ctx.h" 3 : #include "../../flamenco/runtime/sysvar/fd_sysvar_epoch_schedule.h" 4 : 5 : static void 6 0 : dump( fd_epoch_forks_t * epoch_forks ) { 7 0 : for( ulong i = 0UL; i<MAX_EPOCH_FORKS; i++ ) { 8 0 : fd_epoch_fork_elem_t * elem = &epoch_forks->forks[ i ]; 9 0 : FD_LOG_WARNING(("fork elem %lu %lu %lu", elem->parent_slot, elem->epoch, (ulong)elem->epoch_ctx)); 10 0 : } 11 0 : } 12 : 13 : void 14 0 : fd_epoch_forks_new( fd_epoch_forks_t * epoch_forks, void * epoch_ctx_base ) { 15 0 : for( ulong i=0UL; i<MAX_EPOCH_FORKS; i++ ) { 16 0 : fd_epoch_fork_elem_t * epoch_fork = &epoch_forks->forks[i]; 17 0 : epoch_fork->parent_slot = ULONG_MAX; 18 0 : epoch_fork->epoch = ULONG_MAX; 19 0 : epoch_fork->epoch_ctx = NULL; 20 0 : } 21 : 22 0 : epoch_forks->epoch_ctx_base = (uchar *) epoch_ctx_base; 23 0 : epoch_forks->curr_epoch_idx = ULONG_MAX; 24 0 : } 25 : 26 : void 27 0 : fd_epoch_forks_publish( fd_epoch_forks_t * epoch_forks, fd_ghost_t * ghost, ulong root ) { 28 0 : ulong idx = fd_epoch_forks_get_epoch_ctx( epoch_forks, ghost, root, NULL ); 29 : 30 0 : if( FD_LIKELY( idx == epoch_forks->curr_epoch_idx ) ) return; 31 : 32 0 : for( ulong i=0UL; i<MAX_EPOCH_FORKS; i++ ) { 33 0 : if( FD_LIKELY( i != idx && epoch_forks->forks[ i ].parent_slot != ULONG_MAX ) ) { 34 0 : epoch_forks->forks[ i ].parent_slot = ULONG_MAX; 35 0 : epoch_forks->forks[ i ].epoch = ULONG_MAX; 36 0 : fd_exec_epoch_ctx_delete( fd_exec_epoch_ctx_leave( epoch_forks->forks[ i ].epoch_ctx ) ); 37 0 : epoch_forks->forks[ i ].epoch_ctx = NULL; 38 0 : } 39 0 : } 40 : 41 0 : epoch_forks->curr_epoch_idx = idx; 42 0 : } 43 : 44 : uint 45 : fd_epoch_forks_prepare( fd_epoch_forks_t * epoch_forks, 46 : ulong parent_slot, 47 : ulong new_epoch, 48 : fd_epoch_fork_elem_t ** out_fork, 49 0 : ulong vote_accounts_max ) { 50 0 : ulong empty = ULONG_MAX; 51 0 : ulong i = 0UL; 52 : 53 0 : for( ; i<MAX_EPOCH_FORKS; i++ ) { 54 0 : if( epoch_forks->forks[ i ].parent_slot == ULONG_MAX ) { 55 0 : empty = (empty == ULONG_MAX) ? i : empty; 56 0 : continue; 57 0 : } 58 0 : if( epoch_forks->forks[ i ].epoch == new_epoch && epoch_forks->forks[ i ].parent_slot == parent_slot ) { 59 0 : *out_fork = &epoch_forks->forks[ i ]; 60 0 : return 1; 61 0 : } 62 0 : } 63 : 64 0 : if( FD_LIKELY( empty != ULONG_MAX ) ) { 65 0 : epoch_forks->forks[ empty ].parent_slot = parent_slot; 66 0 : epoch_forks->forks[ empty ].epoch = new_epoch; 67 : 68 : /* FIXME DO NOT DYNAMICALLY ALLOCATE MEMORY IN API FUNCTIONS */ 69 0 : uchar * epoch_ctx_mem = epoch_forks->epoch_ctx_base + (empty * fd_ulong_align_up( fd_exec_epoch_ctx_footprint( vote_accounts_max ), fd_exec_epoch_ctx_align() ) ); 70 0 : epoch_forks->forks[ empty ].epoch_ctx = fd_exec_epoch_ctx_join( fd_exec_epoch_ctx_new( epoch_ctx_mem, vote_accounts_max ) ); 71 0 : *out_fork = &epoch_forks->forks[ empty ]; 72 0 : } else { 73 0 : dump( epoch_forks ); 74 0 : FD_LOG_CRIT(("Too many forks for epoch boundary.")); 75 0 : } 76 : 77 0 : return 0; 78 0 : } 79 : 80 : ulong 81 0 : fd_epoch_forks_get_epoch_ctx( fd_epoch_forks_t * epoch_forks, fd_ghost_t * ghost, ulong curr_slot, ulong * opt_prev_slot ) { 82 0 : fd_exec_epoch_ctx_t * epoch_ctx = epoch_forks->forks[ epoch_forks->curr_epoch_idx ].epoch_ctx; 83 0 : fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( epoch_ctx ); 84 0 : ulong epoch = fd_slot_to_epoch( &epoch_bank->epoch_schedule, curr_slot, NULL ); 85 0 : if( FD_LIKELY( epoch == epoch_forks->forks[ epoch_forks->curr_epoch_idx ].epoch ) ) return epoch_forks->curr_epoch_idx; 86 : 87 0 : ulong max_parent_root = 0UL; 88 0 : ulong max_idx = ULONG_MAX; 89 0 : for( ulong i=0; i<MAX_EPOCH_FORKS; i++ ) { 90 0 : fd_epoch_fork_elem_t * elem = &epoch_forks->forks[ i ]; 91 0 : if( elem->parent_slot == ULONG_MAX ) continue; 92 : 93 : /* check if this fork has a parent in the entries list, and isn't the parent itself. */ 94 0 : ulong slot = (opt_prev_slot == NULL) ? curr_slot : *opt_prev_slot; 95 0 : if( elem->parent_slot != slot && elem->parent_slot >= fd_ghost_root(ghost)->slot && fd_ghost_is_ancestor( ghost, elem->parent_slot, slot ) ) { 96 0 : if( elem->parent_slot > max_parent_root ) { 97 0 : max_parent_root = elem->parent_slot; 98 0 : max_idx = i; 99 0 : } 100 0 : } 101 0 : } 102 : 103 0 : return (max_idx != ULONG_MAX) ? max_idx : epoch_forks->curr_epoch_idx; 104 0 : }