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