Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_progcache_fd_progcache_h 2 : #define HEADER_fd_src_flamenco_progcache_fd_progcache_h 3 : 4 : /* fd_progcache.h provides program cache data structures */ 5 : 6 : #include "fd_progcache_rec.h" 7 : #include "../../funk/fd_funk_base.h" 8 : #include "../fd_rwlock.h" 9 : #include "../runtime/fd_runtime_const.h" 10 : #include <stdatomic.h> 11 : 12 : /* fd_progcache_shmem_t is the top-level shared memory data structure 13 : of the progcache. */ 14 : 15 : typedef union fd_funk_txn_xid fd_progcache_xid_t; 16 : 17 12 : #define FD_PROGCACHE_SHMEM_MAGIC (0xf17eda2ce7fc2c03UL) 18 : 19 : #define FD_PROGCACHE_SPAD_MAX (FD_MAX_INSTRUCTION_STACK_DEPTH * (20UL<<20)) 20 : 21 : struct fd_progcache_shmem { 22 : 23 : ulong magic; 24 : ulong wksp_tag; 25 : ulong seed; 26 : 27 : ulong alloc_gaddr; 28 : 29 : struct { 30 : uint max; 31 : ulong map_gaddr; 32 : ulong pool_gaddr; 33 : ulong ele_gaddr; 34 : } rec; 35 : 36 : struct __attribute__((aligned(64))) { 37 : fd_rwlock_t rwlock; 38 : ulong max; 39 : ulong map_gaddr; 40 : ulong pool_gaddr; 41 : ulong ele_gaddr; 42 : uint child_head_idx; 43 : uint child_tail_idx; 44 : fd_funk_txn_xid_t last_publish[1]; /* root XID (initially ULONG_MAX:ULONG_MAX) */ 45 : } txn; 46 : 47 : struct { 48 : fd_rwlock_t lock; 49 : uint head; /* next to evict */ 50 : } clock; 51 : 52 : struct { 53 : fd_rwlock_t lock; 54 : fd_progcache_rec_t rec[ FD_MAX_INSTRUCTION_STACK_DEPTH ]; 55 : uint rec_used; 56 : uint spad_used; 57 : uint spad_off[ FD_MAX_INSTRUCTION_STACK_DEPTH ]; 58 : uchar spad[ FD_PROGCACHE_SPAD_MAX ] __attribute__((aligned(64UL))); 59 : } spill; 60 : 61 : }; 62 : 63 : typedef struct fd_progcache_shmem fd_progcache_shmem_t; 64 : 65 : FD_STATIC_ASSERT( FD_PROGCACHE_SPAD_MAX<=UINT_MAX, "layout" ); 66 : 67 : /* Declare a separately-chained concurrent hash map for cache entries */ 68 : 69 : #define POOL_NAME fd_prog_recp 70 : #define POOL_ELE_T fd_progcache_rec_t 71 : #define POOL_IDX_T uint 72 : #define POOL_NEXT map_next 73 : #define POOL_IMPL_STYLE 1 74 : #include "../../util/tmpl/fd_pool_para.c" 75 : 76 : struct fd_prog_recm_shmem_private_chain { 77 : ulong ver_cnt; 78 : uint head_cidx; 79 : atomic_uchar clock; /* in [0,1] */ 80 : }; 81 : 82 : #define MAP_NAME fd_prog_recm 83 0 : #define MAP_ELE_T fd_progcache_rec_t 84 : #define MAP_KEY_T fd_funk_xid_key_pair_t 85 : #define MAP_KEY pair 86 29810 : #define MAP_KEY_EQ(k0,k1) fd_funk_xid_key_pair_eq((k0),(k1)) 87 62382 : #define MAP_KEY_HASH(k0,seed) fd_funk_xid_key_pair_hash((k0),(seed)) 88 : #define MAP_IDX_T uint 89 0 : #define MAP_NEXT map_next 90 : #define MAP_MAGIC (0xf173da2ce77ecdb8UL) 91 : #define MAP_CUSTOM_CHAIN 1 92 : #define MAP_IMPL_STYLE 1 93 : #include "../../util/tmpl/fd_map_chain_para.c" 94 : 95 : /* Declare a tree / hash map hybrid of fork graph nodes (externally 96 : synchronized) */ 97 : 98 : struct __attribute__((aligned(64))) fd_progcache_txn { 99 : fd_funk_txn_xid_t xid; 100 : uint map_next; 101 : fd_rwlock_t lock; 102 : 103 : uint parent_idx; 104 : uint child_head_idx; 105 : uint child_tail_idx; 106 : uint sibling_prev_idx; 107 : uint sibling_next_idx; 108 : 109 : uint rec_head_idx; 110 : uint rec_tail_idx; 111 : }; 112 : 113 : typedef struct fd_progcache_txn fd_progcache_txn_t; 114 : 115 : #define POOL_NAME fd_prog_txnp 116 : #define POOL_T fd_progcache_txn_t 117 : #define POOL_IDX_T uint 118 110127 : #define POOL_NEXT map_next 119 : #define POOL_IMPL_STYLE 1 120 : #include "../../util/tmpl/fd_pool.c" 121 : 122 : #define MAP_NAME fd_prog_txnm 123 : #define MAP_ELE_T fd_progcache_txn_t 124 : #define MAP_KEY_T fd_funk_txn_xid_t 125 : #define MAP_KEY xid 126 84009 : #define MAP_KEY_EQ(k0,k1) fd_funk_txn_xid_eq((k0),(k1)) 127 202925 : #define MAP_KEY_HASH(k0,seed) fd_funk_txn_xid_hash((k0),(seed)) 128 : #define MAP_IDX_T uint 129 : #define MAP_NEXT map_next 130 : #define MAP_MAGIC (0xf173da2ce77ecdb9UL) 131 : #define MAP_IMPL_STYLE 1 132 : #include "../../util/tmpl/fd_map_chain.c" 133 : 134 : /* Declare fd_progcache_join_t now that we have all dependencies */ 135 : 136 : struct fd_progcache_join { 137 : 138 : fd_progcache_shmem_t * shmem; 139 : 140 : struct { 141 : fd_prog_recm_t map[1]; 142 : fd_prog_recp_t pool[1]; 143 : } rec; 144 : 145 : struct { 146 : fd_prog_txnm_t * map; 147 : fd_progcache_txn_t * pool; 148 : } txn; 149 : 150 : fd_wksp_t * wksp; 151 : fd_alloc_t * alloc; 152 : 153 : }; 154 : 155 : FD_PROTOTYPES_BEGIN 156 : 157 : FD_FN_CONST ulong 158 : fd_progcache_shmem_align( void ); 159 : 160 : FD_FN_CONST ulong 161 : fd_progcache_shmem_footprint( ulong txn_max, 162 : ulong rec_max ); 163 : 164 : fd_progcache_shmem_t * 165 : fd_progcache_shmem_new( void * shmem, 166 : ulong wksp_tag, 167 : ulong seed, 168 : ulong txn_max, 169 : ulong rec_max ); 170 : 171 : fd_progcache_join_t * 172 : fd_progcache_shmem_join( fd_progcache_join_t * ljoin, 173 : fd_progcache_shmem_t * shmem ); 174 : 175 : void * 176 : fd_progcache_shmem_leave( fd_progcache_join_t * ljoin, 177 : fd_progcache_shmem_t ** opt_shmem ); 178 : 179 : void * 180 : fd_progcache_shmem_delete( fd_progcache_shmem_t * shmem ); 181 : 182 : void * 183 : fd_progcache_shmem_delete_fast( fd_progcache_shmem_t * shmem ); 184 : 185 : /* CLOCK cache replacement algo */ 186 : 187 : static inline atomic_uchar * 188 : fd_prog_recm_clock_by_memo( fd_progcache_join_t * ljoin, 189 1404 : ulong memo ) { 190 1404 : return &fd_prog_recm_shmem_private_chain( ljoin->rec.map->map, memo )->clock; 191 1404 : } 192 : 193 : static inline ulong 194 : fd_prog_recm_memo( fd_progcache_join_t * ljoin, 195 0 : fd_funk_rec_key_t const * key ) { 196 0 : return fd_funk_rec_key_hash( key, ljoin->rec.map->map->seed ); 197 0 : } 198 : 199 : static inline void 200 : fd_prog_recm_clock_touch( fd_progcache_join_t * ljoin, 201 1404 : ulong memo ) { 202 1404 : atomic_store_explicit( fd_prog_recm_clock_by_memo( ljoin, memo ), 1, memory_order_relaxed ); 203 1404 : } 204 : 205 : FD_PROTOTYPES_END 206 : 207 : #endif /* HEADER_fd_src_flamenco_progcache_fd_progcache_h */