Line data Source code
1 : #ifndef HEADER_fd_src_choreo_epoch_fd_epoch_h 2 : #define HEADER_fd_src_choreo_epoch_fd_epoch_h 3 : 4 : #include "../fd_choreo_base.h" 5 : #include "../voter/fd_voter.h" 6 : 7 : /* FD_EPOCH_USE_HANDHOLDING: Define this to non-zero at compile time 8 : to turn on additional runtime checks and logging. */ 9 : 10 : #ifndef FD_EPOCH_USE_HANDHOLDING 11 : #define FD_EPOCH_USE_HANDHOLDING 1 12 : #endif 13 : 14 0 : #define FD_EPOCH_MAGIC (0xf17eda2ce7e90c40UL) /* firedancer epoch version 0 */ 15 : 16 : struct __attribute__((aligned(128UL))) fd_epoch { 17 : ulong magic; /* ==FD_EPOCH_MAGIC */ 18 : ulong epoch_gaddr; /* wksp gaddr of this in the backing wksp, non-zero gaddr */ 19 : ulong total_stake; /* total amount of stake in the epoch. */ 20 : ulong first_slot; /* first slot in the epoch */ 21 : ulong last_slot; /* last slot in the epoch */ 22 : 23 : /* voters_gaddr is the global address of a fd_map_dynamic that 24 : contains all voters in the current epoch keyed by pubkey (vote 25 : account address). */ 26 : 27 : ulong voters_gaddr; 28 : }; 29 : typedef struct fd_epoch fd_epoch_t; 30 : 31 : #define MAP_NAME fd_epoch_voters 32 0 : #define MAP_T fd_voter_t 33 0 : #define MAP_KEY_T fd_pubkey_t 34 0 : #define MAP_KEY_NULL (fd_pubkey_t){0} 35 0 : #define MAP_KEY_EQUAL(k0,k1) (!(memcmp((k0).key,(k1).key,sizeof(fd_pubkey_t)))) 36 0 : #define MAP_KEY_INVAL(k) (MAP_KEY_EQUAL((k),MAP_KEY_NULL)) 37 : #define MAP_KEY_EQUAL_IS_SLOW 1 38 0 : #define MAP_KEY_HASH(key) ((key).ui[3]) 39 : #include "../../util/tmpl/fd_map_dynamic.c" 40 : 41 : /* fd_epoch_{align,footprint} return the required alignment and 42 : footprint of a memory region suitable for use as epoch. align is 43 : double cache line to mitigate false sharing. */ 44 : 45 : FD_FN_CONST static inline ulong 46 0 : fd_epoch_align( void ) { 47 0 : return alignof(fd_epoch_t); 48 0 : } 49 : 50 : FD_FN_CONST static inline ulong 51 0 : fd_epoch_footprint( ulong voter_max ) { 52 0 : int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( voter_max ) ) + 2; /* fill ratio <= 0.25 */ 53 0 : return FD_LAYOUT_FINI( 54 0 : FD_LAYOUT_APPEND( 55 0 : FD_LAYOUT_APPEND( 56 0 : FD_LAYOUT_INIT, 57 0 : alignof(fd_epoch_t), sizeof(fd_epoch_t) ), 58 0 : fd_epoch_voters_align(), fd_epoch_voters_footprint( lg_slot_cnt ) ), 59 0 : fd_epoch_align() ); 60 0 : } 61 : 62 : /* fd_epoch_new formats an unused memory region for use as an epoch. mem 63 : is a non-NULL pointer to this region in the local address space with 64 : the required footprint and alignment. */ 65 : 66 : void * 67 : fd_epoch_new( void * mem, ulong voter_max ); 68 : 69 : /* fd_epoch_join joins the caller to the epoch. epoch points to the 70 : first byte of the memory region backing the epoch in the caller's 71 : address space. 72 : 73 : Returns a pointer in the local address space to epoch on success. */ 74 : 75 : fd_epoch_t * 76 : fd_epoch_join( void * epoch ); 77 : 78 : /* fd_epoch_leave leaves a current local join. Returns a pointer to the 79 : underlying shared memory region on success and NULL on failure (logs 80 : details). Reasons for failure include epoch is NULL. */ 81 : 82 : void * 83 : fd_epoch_leave( fd_epoch_t const * epoch ); 84 : 85 : /* fd_epoch_delete unformats a memory region used as an epoch. Assumes 86 : only the local process is joined to the region. Returns a pointer to 87 : the underlying shared memory region or NULL if used obviously in 88 : error (e.g. epoch is obviously not an epoch ... logs details). The 89 : ownership of the memory region is transferred to the caller. */ 90 : 91 : void * 92 : fd_epoch_delete( void * epoch ); 93 : 94 : /* fd_epoch_init initializes a fd_choreo epoch using `epoch_bank`. 95 : Assumes epoch is a valid local join and epoch has not already been 96 : initialized. This should only be called once at the beginning of an 97 : epoch. */ 98 : 99 : void 100 : fd_epoch_init( fd_epoch_t * epoch, 101 : ulong eah_start_slot, 102 : ulong eah_stop_slot, 103 : fd_vote_accounts_global_t const * vote_accounts ); 104 : 105 : /* fd_epoch_fini finishes an epoch. Assumes epoch is a valid local join 106 : and epoch has already been initialized. This should only be called 107 : once at the end of an epoch. */ 108 : 109 : void 110 : fd_epoch_fini( fd_epoch_t * epoch ); 111 : 112 : /* fd_epoch_wksp returns the local join to the wksp backing the epoch. 113 : The lifetime of the returned pointer is at least as long as the 114 : lifetime of the local join. Assumes epoch is a current local 115 : join. */ 116 : 117 : FD_FN_PURE static inline fd_wksp_t * 118 0 : fd_epoch_wksp( fd_epoch_t const * epoch ) { 119 0 : return (fd_wksp_t *)( ( (ulong)epoch ) - epoch->epoch_gaddr ); 120 0 : } 121 : 122 : FD_FN_PURE static inline fd_voter_t * 123 0 : fd_epoch_voters( fd_epoch_t * epoch ) { 124 0 : return fd_wksp_laddr_fast( fd_epoch_wksp( epoch ), epoch->voters_gaddr ); 125 0 : } 126 : 127 : FD_FN_PURE static inline fd_voter_t const * 128 0 : fd_epoch_voters_const( fd_epoch_t const * epoch ) { 129 0 : return fd_wksp_laddr_fast( fd_epoch_wksp( epoch ), epoch->voters_gaddr ); 130 0 : } 131 : 132 : #endif /* HEADER_fd_src_choreo_epoch_fd_epoch_h */