84
84
#define IN_KIND_SNAP (3)
85
85
#define IN_KIND_WRITER (4)
86
86
87
- #define EXEC_TXN_BUSY (0xA)
88
- #define EXEC_TXN_READY (0xB)
89
-
90
87
#define BANK_HASH_CMP_LG_MAX (16UL)
91
88
92
89
struct fd_replay_in_link {
@@ -165,6 +162,8 @@ typedef struct fd_exec_slice fd_exec_slice_t;
165
162
#define DEQUE_MAX USHORT_MAX
166
163
#include "../../util/tmpl/fd_deque_dynamic.c"
167
164
165
+ FD_STATIC_ASSERT ( FD_PACK_MAX_BANK_TILES <=64UL , exec_bitset );
166
+
168
167
struct fd_replay_tile_ctx {
169
168
fd_wksp_t * wksp ;
170
169
fd_wksp_t * status_cache_wksp ;
@@ -221,8 +220,8 @@ struct fd_replay_tile_ctx {
221
220
222
221
/* TODO: Some of these arrays should be bitvecs that get masked into. */
223
222
ulong exec_cnt ;
223
+ ulong exec_ready_bitset ; /* Is tile ready */
224
224
fd_replay_out_link_t exec_out [ FD_PACK_MAX_BANK_TILES ]; /* Sending to exec unexecuted txns */
225
- uchar exec_ready [ FD_PACK_MAX_BANK_TILES ]; /* Is tile ready */
226
225
uint prev_ids [ FD_PACK_MAX_BANK_TILES ]; /* Previous txn id if any */
227
226
ulong * exec_fseq [ FD_PACK_MAX_BANK_TILES ]; /* fseq of the last executed txn */
228
227
@@ -677,9 +676,7 @@ init_after_snapshot( fd_replay_tile_ctx_t * ctx ) {
677
676
snapshot_slot = 1UL ;
678
677
679
678
/* Now setup exec tiles for execution */
680
- for ( ulong i = 0UL ; i < ctx -> exec_cnt ; i ++ ) {
681
- ctx -> exec_ready [ i ] = EXEC_TXN_READY ;
682
- }
679
+ ctx -> exec_ready_bitset = fd_ulong_mask_lsb ( (int )ctx -> exec_cnt );
683
680
}
684
681
685
682
ctx -> snapshot_slot = snapshot_slot ;
@@ -736,12 +733,7 @@ init_after_snapshot( fd_replay_tile_ctx_t * ctx ) {
736
733
737
734
/* Now that the snapshot(s) are done loading, we can mark all of the
738
735
exec tiles as ready. */
739
- for ( ulong i = 0UL ; i < ctx -> exec_cnt ; i ++ ) {
740
- if ( ctx -> exec_ready [ i ] == EXEC_TXN_BUSY ) {
741
- ctx -> exec_ready [ i ] = EXEC_TXN_READY ;
742
- }
743
- }
744
-
736
+ ctx -> exec_ready_bitset = fd_ulong_mask_lsb ( (int )ctx -> exec_cnt );
745
737
746
738
FD_LOG_NOTICE (( "snapshot slot %lu" , snapshot_slot ));
747
739
}
@@ -1171,11 +1163,11 @@ handle_writer_state_updates( fd_replay_tile_ctx_t * ctx ) {
1171
1163
break ;
1172
1164
case FD_WRITER_STATE_TXN_DONE : {
1173
1165
uint txn_id = fd_writer_fseq_get_txn_id ( res );
1174
- ulong exec_tile_id = fd_writer_fseq_get_exec_tile_id ( res );
1175
- if ( ctx -> exec_ready [ exec_tile_id ] == EXEC_TXN_BUSY && ctx -> prev_ids [ exec_tile_id ]!= txn_id ) {
1166
+ int exec_tile_id = fd_writer_fseq_get_exec_tile_id ( res );
1167
+ if ( fd_ulong_extract_bit ( ctx -> exec_ready_bitset , exec_tile_id ) == 0 && ctx -> prev_ids [ exec_tile_id ]!= txn_id ) {
1176
1168
//FD_LOG_DEBUG(( "Ack that exec tile idx=%lu txn id=%u has been finalized by writer tile %lu", exec_tile_id, txn_id, i ));
1177
- ctx -> exec_ready [ exec_tile_id ] = EXEC_TXN_READY ;
1178
- ctx -> prev_ids [ exec_tile_id ] = txn_id ;
1169
+ ctx -> exec_ready_bitset = fd_ulong_set_bit ( ctx -> exec_ready_bitset , exec_tile_id ) ;
1170
+ ctx -> prev_ids [ exec_tile_id ] = txn_id ;
1179
1171
fd_fseq_update ( ctx -> writer_fseq [ i ], FD_WRITER_STATE_READY );
1180
1172
}
1181
1173
break ;
@@ -1468,18 +1460,6 @@ handle_new_slice( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
1468
1460
fd_bank_shred_cnt_set ( ctx -> slot_ctx -> bank , fd_bank_shred_cnt_get ( ctx -> slot_ctx -> bank ) + data_cnt );
1469
1461
}
1470
1462
1471
- static ulong
1472
- get_free_exec_tiles ( fd_replay_tile_ctx_t * ctx , uchar * exec_free_idx ) {
1473
- ulong cnt = 0UL ;
1474
- for ( uchar i = 0 ; i < ctx -> exec_cnt ; i ++ ) {
1475
- if ( ctx -> exec_ready [ i ]== EXEC_TXN_READY ) {
1476
- exec_free_idx [ cnt ] = i ;
1477
- cnt ++ ;
1478
- }
1479
- }
1480
- return cnt ;
1481
- }
1482
-
1483
1463
static void
1484
1464
exec_slice_fini_slot ( fd_replay_tile_ctx_t * ctx , fd_stem_context_t * stem ) {
1485
1465
@@ -1603,8 +1583,6 @@ exec_slice_fini_slot( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
1603
1583
1604
1584
static void
1605
1585
exec_and_handle_slice ( fd_replay_tile_ctx_t * ctx , fd_stem_context_t * stem ) {
1606
- uchar exec_free_idx [ FD_PACK_MAX_BANK_TILES ];
1607
- ulong free_exec_cnt = get_free_exec_tiles ( ctx , exec_free_idx );
1608
1586
1609
1587
/* If there are no txns left to execute in the microblock and the
1610
1588
exec tiles are not busy, then we are ready to either start
@@ -1613,7 +1591,7 @@ exec_and_handle_slice( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
1613
1591
We have to synchronize on the the microblock boundary because we
1614
1592
only have the guarantee that all transactions within the same
1615
1593
microblock can be executed in parallel. */
1616
- if ( !fd_slice_exec_txn_ready ( & ctx -> slice_exec_ctx ) && free_exec_cnt == ctx -> exec_cnt ) {
1594
+ if ( !fd_slice_exec_txn_ready ( & ctx -> slice_exec_ctx ) && ctx -> exec_ready_bitset == fd_ulong_mask_lsb ( ( int ) ctx -> exec_cnt ) ) {
1617
1595
if ( fd_slice_exec_microblock_ready ( & ctx -> slice_exec_ctx ) ) {
1618
1596
fd_slice_exec_microblock_parse ( & ctx -> slice_exec_ctx );
1619
1597
} else if ( fd_slice_exec_slice_ready ( & ctx -> slice_exec_ctx ) ) {
@@ -1630,13 +1608,15 @@ exec_and_handle_slice( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
1630
1608
1631
1609
/* At this point, we know that we have some quantity of transactions
1632
1610
in a microblock that we are ready to execute. */
1633
- for ( ulong i = 0UL ; i < free_exec_cnt ; i ++ ) {
1611
+ for ( int i = 0 ; i < fd_ulong_popcnt ( ctx -> exec_ready_bitset ) ; i ++ ) {
1634
1612
1635
1613
if ( !fd_slice_exec_txn_ready ( & ctx -> slice_exec_ctx ) ) {
1636
1614
return ;
1637
1615
}
1638
1616
1639
- ulong exec_idx = exec_free_idx [ i ];
1617
+ int exec_idx = fd_ulong_find_lsb ( ctx -> exec_ready_bitset );
1618
+ /* Mark the exec tile as busy */
1619
+ ctx -> exec_ready_bitset = fd_ulong_pop_lsb ( ctx -> exec_ready_bitset );
1640
1620
1641
1621
ulong tsorig = fd_frag_meta_ts_comp ( fd_tickcount () );
1642
1622
@@ -1649,9 +1629,6 @@ exec_and_handle_slice( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
1649
1629
over all accounts a second time. */
1650
1630
fd_runtime_update_program_cache ( ctx -> slot_ctx , & txn_p , ctx -> runtime_spad );
1651
1631
1652
- /* Mark the exec tile as busy */
1653
- ctx -> exec_ready [ exec_idx ] = EXEC_TXN_BUSY ;
1654
-
1655
1632
/* Dispatch dcache to exec tile */
1656
1633
fd_replay_out_link_t * exec_out = & ctx -> exec_out [ exec_idx ];
1657
1634
fd_runtime_public_txn_msg_t * exec_msg = (fd_runtime_public_txn_msg_t * )fd_chunk_to_laddr ( exec_out -> mem , exec_out -> chunk );
@@ -2017,9 +1994,9 @@ unprivileged_init( fd_topo_t * topo,
2017
1994
FD_LOG_CRIT (( "too many exec tiles %lu" , ctx -> exec_cnt ));
2018
1995
}
2019
1996
1997
+ /* Mark all initial state as not being ready. */
1998
+ ctx -> exec_ready_bitset = 0UL ;
2020
1999
for ( ulong i = 0UL ; i < ctx -> exec_cnt ; i ++ ) {
2021
- /* Mark all initial state as not being ready. */
2022
- ctx -> exec_ready [ i ] = EXEC_TXN_BUSY ;
2023
2000
ctx -> prev_ids [ i ] = FD_EXEC_ID_SENTINEL ;
2024
2001
2025
2002
ulong exec_fseq_id = fd_pod_queryf_ulong ( topo -> props , ULONG_MAX , "exec_fseq.%lu" , i );
0 commit comments