Line data Source code
1 : #include "fd_progcache.h"
2 :
3 : #define POOL_NAME fd_prog_recp
4 59596 : #define POOL_ELE_T fd_progcache_rec_t
5 : #define POOL_IDX_T uint
6 71875 : #define POOL_NEXT map_next
7 : #define POOL_IMPL_STYLE 2
8 : #include "../../util/tmpl/fd_pool_para.c"
9 :
10 : #define MAP_NAME fd_prog_recm
11 31231 : #define MAP_ELE_T fd_progcache_rec_t
12 0 : #define MAP_KEY_T fd_funk_xid_key_pair_t
13 29793 : #define MAP_KEY pair
14 : #define MAP_KEY_EQ(k0,k1) fd_funk_xid_key_pair_eq((k0),(k1))
15 : #define MAP_KEY_HASH(k0,seed) fd_funk_xid_key_pair_hash((k0),(seed))
16 31222 : #define MAP_IDX_T uint
17 59606 : #define MAP_NEXT map_next
18 12 : #define MAP_MAGIC (0xf173da2ce77ecdb8UL)
19 : #define MAP_CUSTOM_CHAIN 1
20 : #define MAP_IMPL_STYLE 2
21 : #include "../../util/tmpl/fd_map_chain_para.c"
22 :
23 : #define POOL_NAME fd_prog_txnp
24 36 : #define POOL_T fd_progcache_txn_t
25 : #define POOL_IDX_T uint
26 192 : #define POOL_NEXT map_next
27 : #define POOL_IMPL_STYLE 2
28 : #include "../../util/tmpl/fd_pool.c"
29 :
30 : #define MAP_NAME fd_prog_txnm
31 : #define MAP_ELE_T fd_progcache_txn_t
32 : #define MAP_KEY_T fd_funk_txn_xid_t
33 55097 : #define MAP_KEY xid
34 : #define MAP_KEY_EQ(k0,k1) fd_funk_txn_xid_eq((k0),(k1))
35 : #define MAP_KEY_HASH(k0,seed) fd_funk_txn_xid_hash((k0),(seed))
36 229315 : #define MAP_IDX_T uint
37 111893 : #define MAP_NEXT map_next
38 12 : #define MAP_MAGIC (0xf173da2ce77ecdb9UL)
39 : #define MAP_IMPL_STYLE 2
40 : #include "../../util/tmpl/fd_map_chain.c"
41 :
42 : FD_FN_CONST ulong
43 96 : fd_progcache_shmem_align( void ) {
44 96 : return fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max(
45 96 : alignof(fd_progcache_shmem_t),
46 96 : fd_prog_txnm_align() ),
47 96 : fd_prog_txnp_align() ),
48 96 : alignof(fd_progcache_txn_t) ),
49 96 : fd_prog_recm_align() ),
50 96 : fd_prog_recp_align() ),
51 96 : alignof(fd_progcache_rec_t) ),
52 96 : fd_alloc_align() );
53 96 : }
54 :
55 : FD_FN_CONST ulong
56 : fd_progcache_shmem_footprint( ulong txn_max,
57 24 : ulong rec_max ) {
58 24 : if( FD_UNLIKELY( txn_max>UINT_MAX ) ) return 0UL;
59 24 : if( FD_UNLIKELY( rec_max>UINT_MAX ) ) return 0UL;
60 :
61 24 : ulong l = FD_LAYOUT_INIT;
62 :
63 24 : l = FD_LAYOUT_APPEND( l, alignof(fd_progcache_shmem_t), sizeof(fd_progcache_shmem_t) );
64 :
65 24 : ulong txn_chain_cnt = fd_prog_txnm_chain_cnt_est( txn_max );
66 24 : l = FD_LAYOUT_APPEND( l, fd_prog_txnm_align(), fd_prog_txnm_footprint( txn_chain_cnt ) );
67 24 : l = FD_LAYOUT_APPEND( l, fd_prog_txnp_align(), fd_prog_txnp_footprint( txn_max ) );
68 :
69 24 : ulong rec_chain_cnt = fd_prog_recm_chain_cnt_est( rec_max );
70 24 : l = FD_LAYOUT_APPEND( l, fd_prog_recm_align(), fd_prog_recm_footprint( rec_chain_cnt ) );
71 24 : l = FD_LAYOUT_APPEND( l, fd_prog_recp_align(), fd_prog_recp_footprint() );
72 24 : l = FD_LAYOUT_APPEND( l, alignof(fd_progcache_rec_t), sizeof(fd_progcache_rec_t) * rec_max );
73 :
74 24 : l = FD_LAYOUT_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
75 :
76 24 : return FD_LAYOUT_FINI( l, fd_progcache_shmem_align() );
77 24 : }
78 :
79 : fd_progcache_shmem_t *
80 : fd_progcache_shmem_new( void * shmem,
81 : ulong wksp_tag,
82 : ulong seed,
83 : ulong txn_max,
84 12 : ulong rec_max ) {
85 12 : fd_progcache_shmem_t * pc = shmem;
86 12 : fd_wksp_t * wksp = fd_wksp_containing( pc );
87 :
88 12 : if( FD_UNLIKELY( !pc ) ) {
89 0 : FD_LOG_WARNING(( "NULL shmem" ));
90 0 : return NULL;
91 0 : }
92 :
93 12 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)pc, fd_progcache_shmem_align() ) ) ) {
94 0 : FD_LOG_WARNING(( "misaligned shmem" ));
95 0 : return NULL;
96 0 : }
97 :
98 12 : if( FD_UNLIKELY( !wksp_tag ) ) {
99 0 : FD_LOG_WARNING(( "bad wksp_tag" ));
100 0 : return NULL;
101 0 : }
102 :
103 12 : if( FD_UNLIKELY( !wksp ) ) {
104 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" ));
105 0 : return NULL;
106 0 : }
107 :
108 12 : if( FD_UNLIKELY( !txn_max || txn_max>UINT_MAX ) ) {
109 0 : FD_LOG_WARNING(( "invalid txn_max" ));
110 0 : return NULL;
111 0 : }
112 :
113 12 : if( FD_UNLIKELY( !rec_max || rec_max>UINT_MAX ) ) {
114 0 : FD_LOG_WARNING(( "invalid rec_max" ));
115 0 : return NULL;
116 0 : }
117 :
118 12 : FD_SCRATCH_ALLOC_INIT( l, pc+1 );
119 :
120 12 : ulong txn_chain_cnt = fd_prog_txnm_chain_cnt_est( txn_max );
121 12 : void * txn_map = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_txnm_align(), fd_prog_txnm_footprint( txn_chain_cnt ) );
122 12 : void * txn_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_txnp_align(), fd_prog_txnp_footprint( txn_max ) );
123 :
124 0 : ulong rec_chain_cnt = fd_prog_recm_chain_cnt_est( rec_max );
125 12 : void * rec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_recm_align(), fd_prog_recm_footprint( rec_chain_cnt ) );
126 12 : void * rec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_recp_align(), fd_prog_recp_footprint() );
127 12 : fd_progcache_rec_t * rec_ele = (fd_progcache_rec_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_progcache_rec_t), sizeof(fd_progcache_rec_t) * rec_max );
128 :
129 12 : void * alloc = FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
130 :
131 12 : FD_TEST( _l == (ulong)pc + fd_progcache_shmem_footprint( txn_max, rec_max ) );
132 :
133 12 : fd_memset( pc, 0, sizeof(fd_progcache_shmem_t) );
134 :
135 12 : pc->wksp_tag = wksp_tag;
136 12 : pc->seed = seed;
137 :
138 12 : pc->txn.map_gaddr = fd_wksp_gaddr_fast( wksp, fd_prog_txnm_new( txn_map, txn_chain_cnt, seed ) );
139 12 : void * txn_pool2 = fd_prog_txnp_new( txn_pool, txn_max );
140 12 : pc->txn.pool_gaddr = fd_wksp_gaddr_fast( wksp, txn_pool2 );
141 12 : fd_progcache_txn_t * txn_ele = fd_prog_txnp_join( txn_pool2 );
142 12 : pc->txn.ele_gaddr = fd_wksp_gaddr_fast( wksp, txn_ele );
143 12 : fd_prog_txnp_leave( txn_ele );
144 12 : pc->txn.max = txn_max;
145 12 : pc->txn.child_head_idx = UINT_MAX;
146 12 : pc->txn.child_tail_idx = UINT_MAX;
147 12 : fd_funk_txn_xid_set_root( pc->txn.last_publish );
148 204 : for( ulong i=0UL; i<txn_max; i++ ) {
149 192 : fd_rwlock_new( &txn_ele[ i ].lock );
150 192 : }
151 :
152 12 : pc->rec.map_gaddr = fd_wksp_gaddr_fast( wksp, fd_prog_recm_new( rec_map, rec_chain_cnt, seed ) );
153 12 : void * rec_pool2 = fd_prog_recp_new( rec_pool );
154 12 : pc->rec.pool_gaddr = fd_wksp_gaddr_fast( wksp, rec_pool2 );
155 12 : fd_prog_recp_t rec_join[1];
156 12 : fd_prog_recp_join( rec_join, rec_pool2, rec_ele, rec_max );
157 12 : fd_prog_recp_reset( rec_join, 0UL );
158 12 : pc->rec.ele_gaddr = fd_wksp_gaddr_fast( wksp, rec_ele );
159 12 : fd_prog_recp_leave( rec_join );
160 12 : pc->rec.max = (uint)rec_max;
161 12300 : for( ulong i=0UL; i<rec_max; i++ ) {
162 12288 : fd_rwlock_new( &rec_ele[ i ].lock );
163 12288 : }
164 :
165 12 : fd_rwlock_new( &pc->clock.lock );
166 12 : pc->clock.head = 0U;
167 :
168 12 : fd_rwlock_new( &pc->spill.lock );
169 12 : pc->spill.spad_used = 0U;
170 :
171 12 : pc->alloc_gaddr = fd_wksp_gaddr_fast( wksp, fd_alloc_join( fd_alloc_new( alloc, wksp_tag ), 0UL ) );
172 :
173 12 : FD_COMPILER_MFENCE();
174 12 : FD_VOLATILE( pc->magic ) = FD_PROGCACHE_SHMEM_MAGIC;
175 12 : FD_COMPILER_MFENCE();
176 :
177 12 : return (void *)pc;
178 12 : }
179 :
180 : fd_progcache_join_t *
181 : fd_progcache_shmem_join( fd_progcache_join_t * ljoin,
182 12 : fd_progcache_shmem_t * shmem ) {
183 :
184 12 : if( FD_UNLIKELY( !shmem ) ) {
185 0 : FD_LOG_WARNING(( "NULL shmem" ));
186 0 : return NULL;
187 0 : }
188 12 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
189 0 : FD_LOG_WARNING(( "misaligned shmem" ));
190 0 : return NULL;
191 0 : }
192 12 : fd_wksp_t * wksp = fd_wksp_containing( shmem );
193 12 : if( FD_UNLIKELY( !wksp ) ) {
194 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" ));
195 0 : return NULL;
196 0 : }
197 12 : if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
198 0 : FD_LOG_WARNING(( "bad magic" ));
199 0 : return NULL;
200 0 : }
201 :
202 12 : if( FD_UNLIKELY( !ljoin ) ) {
203 0 : FD_LOG_WARNING(( "NULL join" ));
204 0 : return NULL;
205 0 : }
206 :
207 12 : memset( ljoin, 0, sizeof(fd_progcache_join_t) );
208 :
209 12 : ljoin->shmem = shmem;
210 12 : ljoin->wksp = wksp;
211 :
212 12 : ljoin->txn.pool = fd_prog_txnp_join( fd_wksp_laddr( wksp, shmem->txn.pool_gaddr ) );
213 12 : if( FD_UNLIKELY( !ljoin->txn.pool ) ) {
214 0 : FD_LOG_WARNING(( "fd_prog_txnp_join failed" ));
215 0 : return NULL;
216 0 : }
217 12 : ljoin->txn.map = fd_prog_txnm_join( fd_wksp_laddr( wksp, shmem->txn.map_gaddr ) );
218 12 : if( FD_UNLIKELY( !ljoin->txn.map ) ) {
219 0 : FD_LOG_WARNING(( "fd_prog_txnm_join failed" ));
220 0 : return NULL;
221 0 : }
222 12 : if( FD_UNLIKELY( !fd_prog_recm_join( ljoin->rec.map, fd_wksp_laddr( wksp, shmem->rec.map_gaddr ), fd_wksp_laddr( wksp, shmem->rec.ele_gaddr ), shmem->rec.max ) ) ) {
223 0 : FD_LOG_WARNING(( "fd_prog_recm_join failed" ));
224 0 : return NULL;
225 0 : }
226 12 : if( FD_UNLIKELY( !fd_prog_recp_join( ljoin->rec.pool, fd_wksp_laddr( wksp, shmem->rec.pool_gaddr ), fd_wksp_laddr( wksp, shmem->rec.ele_gaddr ), shmem->rec.max ) ) ) {
227 0 : FD_LOG_WARNING(( "fd_prog_recp_join failed" ));
228 0 : return NULL;
229 0 : }
230 :
231 12 : if( FD_UNLIKELY( !( ljoin->alloc = fd_alloc_join( fd_wksp_laddr( wksp, shmem->alloc_gaddr ), fd_tile_idx() ) ) ) ) {
232 0 : FD_LOG_WARNING(( "fd_alloc_join failed" ));
233 0 : return NULL;
234 0 : }
235 :
236 12 : return ljoin;
237 12 : }
238 :
239 : void *
240 : fd_progcache_shmem_leave( fd_progcache_join_t * ljoin,
241 12 : fd_progcache_shmem_t ** opt_shmem ) {
242 :
243 12 : if( FD_UNLIKELY( !ljoin ) ) {
244 0 : FD_LOG_WARNING(( "NULL join" ));
245 0 : if( opt_shmem ) *opt_shmem = NULL;
246 0 : return NULL;
247 0 : }
248 :
249 12 : void * shmem = ljoin->shmem;
250 :
251 12 : memset( ljoin, 0, sizeof(fd_progcache_join_t) );
252 :
253 12 : if( opt_shmem ) *opt_shmem = shmem;
254 12 : return shmem;
255 12 : }
256 :
257 : void *
258 12 : fd_progcache_shmem_delete( fd_progcache_shmem_t * shmem ) {
259 :
260 12 : if( FD_UNLIKELY( !shmem ) ) {
261 0 : FD_LOG_WARNING(( "NULL shmem" ));
262 0 : return NULL;
263 0 : }
264 :
265 12 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
266 0 : FD_LOG_WARNING(( "misaligned shmem" ));
267 0 : return NULL;
268 0 : }
269 :
270 12 : fd_wksp_t * wksp = fd_wksp_containing( shmem );
271 12 : if( FD_UNLIKELY( !wksp ) ) {
272 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" ));
273 0 : return NULL;
274 0 : }
275 :
276 12 : if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
277 0 : FD_LOG_WARNING(( "bad magic" ));
278 0 : return NULL;
279 0 : }
280 :
281 : /* Free all fd_alloc allocations made, individually
282 : (FIXME consider walking the element pool instead of the map?) */
283 :
284 12 : fd_alloc_t * alloc = fd_alloc_join( fd_wksp_laddr_fast( wksp, shmem->alloc_gaddr ), fd_tile_idx() );
285 :
286 12 : void * shmap = fd_wksp_laddr_fast( wksp, shmem->rec.map_gaddr );
287 12 : void * shele = fd_wksp_laddr_fast( wksp, shmem->rec.ele_gaddr );
288 12 : fd_prog_recm_t rec_map[1];
289 12 : if( FD_UNLIKELY( !fd_prog_recm_join( rec_map, shmap, shele, 0UL ) ) ) {
290 0 : FD_LOG_ERR(( "failed to join rec_map (corrupt funk?)" ));
291 0 : return NULL;
292 0 : }
293 12 : ulong chain_cnt = fd_prog_recm_chain_cnt( rec_map );
294 6156 : for( ulong chain_idx=0UL; chain_idx<chain_cnt; chain_idx++ ) {
295 6144 : for(
296 6144 : fd_prog_recm_iter_t iter = fd_prog_recm_iter( rec_map, chain_idx );
297 6144 : !fd_prog_recm_iter_done( iter );
298 6144 : iter = fd_prog_recm_iter_next( iter )
299 6144 : ) {
300 0 : fd_progcache_rec_t * rec = fd_prog_recm_iter_ele( iter );
301 0 : if( rec->data_gaddr ) {
302 0 : fd_alloc_free( alloc, fd_wksp_laddr_fast( wksp, rec->data_gaddr ) );
303 0 : }
304 0 : rec->data_gaddr = 0UL;
305 0 : rec->data_max = 0U;
306 0 : }
307 6144 : }
308 :
309 12 : fd_prog_recm_leave( rec_map );
310 :
311 12 : FD_COMPILER_MFENCE();
312 12 : FD_VOLATILE( shmem->magic ) = 0UL;
313 12 : FD_COMPILER_MFENCE();
314 :
315 : /* Free the fd_alloc instance */
316 :
317 12 : fd_wksp_free_laddr( fd_alloc_delete( fd_alloc_leave( alloc ) ) );
318 :
319 12 : return shmem;
320 12 : }
321 :
322 : void *
323 0 : fd_progcache_shmem_delete_fast( fd_progcache_shmem_t * shmem ) {
324 :
325 0 : if( FD_UNLIKELY( !shmem ) ) {
326 0 : FD_LOG_WARNING(( "NULL shmem" ));
327 0 : return NULL;
328 0 : }
329 :
330 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
331 0 : FD_LOG_WARNING(( "misaligned shmem" ));
332 0 : return NULL;
333 0 : }
334 :
335 0 : if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
336 0 : FD_LOG_WARNING(( "bad magic" ));
337 0 : return NULL;
338 0 : }
339 :
340 0 : fd_wksp_t * wksp = fd_wksp_containing( shmem );
341 0 : if( FD_UNLIKELY( !wksp ) ) {
342 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" ));
343 0 : return NULL;
344 0 : }
345 :
346 0 : ulong const tags[1] = { shmem->wksp_tag };
347 0 : fd_wksp_tag_free( wksp, tags, 1UL );
348 :
349 0 : return shmem;
350 0 : }
|