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 pubkey_null 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, fd_epoch_bank_t const * epoch_bank ); 101 : 102 : /* fd_epoch_fini finishes an epoch. Assumes epoch is a valid local join 103 : and epoch has already been initialized. This should only be called 104 : once at the end of an epoch. */ 105 : 106 : void 107 : fd_epoch_fini( fd_epoch_t * epoch ); 108 : 109 : /* fd_epoch_wksp returns the local join to the wksp backing the epoch. 110 : The lifetime of the returned pointer is at least as long as the 111 : lifetime of the local join. Assumes epoch is a current local 112 : join. */ 113 : 114 : FD_FN_PURE static inline fd_wksp_t * 115 0 : fd_epoch_wksp( fd_epoch_t const * epoch ) { 116 0 : return (fd_wksp_t *)( ( (ulong)epoch ) - epoch->epoch_gaddr ); 117 0 : } 118 : 119 : FD_FN_PURE static inline fd_voter_t * 120 0 : fd_epoch_voters( fd_epoch_t * epoch ) { 121 0 : return fd_wksp_laddr_fast( fd_epoch_wksp( epoch ), epoch->voters_gaddr ); 122 0 : } 123 : 124 : FD_FN_PURE static inline fd_voter_t const * 125 0 : fd_epoch_voters_const( fd_epoch_t const * epoch ) { 126 0 : return fd_wksp_laddr_fast( fd_epoch_wksp( epoch ), epoch->voters_gaddr ); 127 0 : } 128 : 129 : #endif /* HEADER_fd_src_choreo_epoch_fd_epoch_h */