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