Skip to content

Commit 3166238

Browse files
add txn lock
1 parent 78ca44f commit 3166238

File tree

9 files changed

+114
-2
lines changed

9 files changed

+114
-2
lines changed

src/discof/replay/fd_replay_tile.c

+14
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,12 @@ checkpt( fd_replay_tile_ctx_t * ctx ) {
560560

561561
static void
562562
funk_cancel( fd_replay_tile_ctx_t * ctx, ulong mismatch_slot ) {
563+
fd_funkier_txn_start_write( ctx->funk );
563564
fd_funkier_txn_xid_t xid = { .ul = { mismatch_slot, mismatch_slot } };
564565
fd_funkier_txn_map_t txn_map = fd_funkier_txn_map( ctx->funk, fd_funkier_wksp( ctx->funk ) );
565566
fd_funkier_txn_t * mismatch_txn = fd_funkier_txn_query( &xid, &txn_map );
566567
FD_TEST( fd_funkier_txn_cancel( ctx->funk, mismatch_txn, 1 ) );
568+
fd_funkier_txn_end_write( ctx->funk );
567569
}
568570

569571
struct fd_status_check_ctx {
@@ -590,6 +592,8 @@ txncache_publish( fd_replay_tile_ctx_t * ctx,
590592
return;
591593
}
592594

595+
fd_funkier_txn_start_read( ctx->funk );
596+
593597
fd_funkier_txn_t * txn = to_root_txn;
594598
fd_funkier_txn_pool_t txn_pool = fd_funkier_txn_pool( ctx->funk, fd_funkier_wksp( ctx->funk ) );
595599
while( txn!=rooted_txn ) {
@@ -603,6 +607,8 @@ txncache_publish( fd_replay_tile_ctx_t * ctx,
603607
}
604608
txn = fd_funkier_txn_parent( txn, &txn_pool );
605609
}
610+
611+
fd_funkier_txn_end_read( ctx->funk );
606612
}
607613

608614
static void
@@ -679,6 +685,8 @@ funk_publish( fd_replay_tile_ctx_t * ctx,
679685
ulong wmk,
680686
uchar is_constipated ) {
681687

688+
fd_funkier_txn_start_write( ctx->funk );
689+
682690
fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( ctx->slot_ctx->epoch_ctx );
683691
fd_funkier_txn_pool_t txn_pool = fd_funkier_txn_pool( ctx->funk, fd_funkier_wksp( ctx->funk ) );
684692

@@ -818,6 +826,8 @@ funk_publish( fd_replay_tile_ctx_t * ctx,
818826
}
819827
}
820828
}
829+
830+
fd_funkier_txn_end_write( ctx->funk );
821831
}
822832

823833
static fd_funkier_txn_t*
@@ -982,7 +992,9 @@ funk_and_txncache_publish( fd_replay_tile_ctx_t * ctx, ulong wmk, fd_funkier_txn
982992

983993
txncache_publish( ctx, to_root_txn, rooted_txn );
984994

995+
fd_funkier_txn_start_write( ctx->funk );
985996
funk_publish( ctx, to_root_txn, wmk, is_constipated );
997+
fd_funkier_txn_end_write( ctx->funk );
986998

987999
/* Update the snapshot state and determine if one is ready to be created. */
9881000

@@ -1260,7 +1272,9 @@ prepare_new_block_execution( fd_replay_tile_ctx_t * ctx,
12601272
}
12611273
xid.ul[0] = fork->slot_ctx.slot_bank.slot;
12621274
/* push a new transaction on the stack */
1275+
fd_funkier_txn_start_write( ctx->funk );
12631276
fork->slot_ctx.funk_txn = fd_funkier_txn_prepare(ctx->funk, fork->slot_ctx.funk_txn, &xid, 1);
1277+
fd_funkier_txn_end_write( ctx->funk );
12641278

12651279
fd_runtime_block_pre_execute_process_new_epoch( &fork->slot_ctx,
12661280
ctx->tpool,

src/discof/restart/fd_restart.c

+2
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ fd_restart_find_heaviest_fork_bank_hash( fd_restart_t * restart,
210210
*out_need_repair = 0;
211211
} else {
212212
/* Cancel any leftover in-preparation transactions from funk */
213+
fd_funkier_txn_start_write( funk );
213214
fd_funkier_txn_cancel_all( funk, 1 );
215+
fd_funkier_txn_end_write( funk );
214216

215217
*out_need_repair = 1;
216218
}

src/discof/restart/fd_restart_tile.c

+2
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,11 @@ after_frag( fd_restart_tile_ctx_t * ctx,
360360
fd_funkier_rec_publish( prepare );
361361

362362
/* Publish the txn in funk */
363+
fd_funkier_txn_start_write( ctx->funk );
363364
if( FD_UNLIKELY( !fd_funkier_txn_publish( ctx->funk, funk_txn, 1 ) ) ) {
364365
FD_LOG_ERR(( "Wen-restart fails at funk txn publish" ));
365366
}
367+
fd_funkier_txn_end_write( ctx->funk );
366368

367369
/* Copy the bank hash of HeaviestForkSlot to fd_restart_t */
368370
fd_memcpy( &ctx->restart->heaviest_fork_bank_hash, &slot_bank.banks_hash, sizeof(fd_hash_t) );

src/flamenco/runtime/fd_runtime.c

+12
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,9 @@ fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
21912191
/* Start a funk write txn */
21922192
fd_funkier_txn_t * parent_txn = slot_ctx->funk_txn;
21932193
fd_funkier_txn_xid_t migration_xid = fd_funkier_generate_xid();
2194+
fd_funkier_txn_start_write( slot_ctx->acc_mgr->funk );
21942195
slot_ctx->funk_txn = fd_funkier_txn_prepare( slot_ctx->acc_mgr->funk, slot_ctx->funk_txn, &migration_xid, 0UL );
2196+
fd_funkier_txn_end_write( slot_ctx->acc_mgr->funk );
21952197

21962198
/* Attempt serialization of program account. If the program is stateless, we want to create the account. Otherwise,
21972199
we want a writable handle to modify the existing account.
@@ -2270,13 +2272,17 @@ fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
22702272
a BPF cache entry here because the program is technically "delayed visibility", so the program
22712273
should not be invokable until the next slot. The cache entry will be created at the end of the
22722274
block as a part of the finalize routine. */
2275+
fd_funkier_txn_start_write( slot_ctx->acc_mgr->funk );
22732276
fd_funkier_txn_publish_into_parent( slot_ctx->acc_mgr->funk, slot_ctx->funk_txn, 1 );
2277+
fd_funkier_txn_end_write( slot_ctx->acc_mgr->funk );
22742278
slot_ctx->funk_txn = parent_txn;
22752279
return;
22762280

22772281
fail:
22782282
/* Cancel the in-preparation transaction and discard any in-progress changes. */
2283+
fd_funkier_txn_start_write( slot_ctx->acc_mgr->funk );
22792284
fd_funkier_txn_cancel( slot_ctx->acc_mgr->funk, slot_ctx->funk_txn, 0UL );
2285+
fd_funkier_txn_end_write( slot_ctx->acc_mgr->funk );
22802286
slot_ctx->funk_txn = parent_txn;
22812287
}
22822288

@@ -3603,13 +3609,15 @@ fd_runtime_block_verify_tpool( fd_exec_slot_ctx_t * slot_ctx,
36033609
} FD_SPAD_FRAME_END;
36043610
}
36053611

3612+
/* Should only be called in offline replay */
36063613
static int
36073614
fd_runtime_publish_old_txns( fd_exec_slot_ctx_t * slot_ctx,
36083615
fd_capture_ctx_t * capture_ctx,
36093616
fd_tpool_t * tpool,
36103617
fd_spad_t * runtime_spad ) {
36113618
/* Publish any transaction older than 31 slots */
36123619
fd_funkier_t * funk = slot_ctx->acc_mgr->funk;
3620+
fd_funkier_txn_start_write( slot_ctx->acc_mgr->funk );
36133621
fd_funkier_txn_pool_t txnpool = fd_funkier_txn_pool( funk, fd_funkier_wksp( funk ) );
36143622
fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
36153623

@@ -3665,6 +3673,8 @@ fd_runtime_publish_old_txns( fd_exec_slot_ctx_t * slot_ctx,
36653673
}
36663674
}
36673675

3676+
fd_funkier_txn_end_write( slot_ctx->acc_mgr->funk );
3677+
36683678
return 0;
36693679
}
36703680

@@ -3819,7 +3829,9 @@ fd_runtime_block_eval_tpool( fd_exec_slot_ctx_t * slot_ctx,
38193829
/* Start a new funk txn. */
38203830

38213831
fd_funkier_txn_xid_t xid = { .ul = { slot_ctx->slot_bank.slot, slot_ctx->slot_bank.slot } };
3832+
fd_funkier_txn_start_write( funk );
38223833
slot_ctx->funk_txn = fd_funkier_txn_prepare( funk, slot_ctx->funk_txn, &xid, 1 );
3834+
fd_funkier_txn_end_write( funk );
38233835

38243836
/* Capturing block-agnostic state in preparation for the epoch boundary */
38253837
uchar dump_block = capture_ctx && slot_ctx->slot_bank.slot >= capture_ctx->dump_proto_start_slot && capture_ctx->dump_block_to_pb;

src/flamenco/runtime/program/fd_bpf_program_util.c

+12-1
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,18 @@ fd_bpf_scan_and_create_bpf_program_cache_entry_tpool( fd_exec_slot_ctx_t * slot_
357357
/* Use random-ish xid to avoid concurrency issues */
358358
fd_funkier_txn_xid_t cache_xid = fd_funkier_generate_xid();
359359

360+
fd_funkier_txn_start_write( funk );
360361
fd_funkier_txn_t * cache_txn = fd_funkier_txn_prepare( funk, slot_ctx->funk_txn, &cache_xid, 1 );
361362
if( !cache_txn ) {
362363
FD_LOG_ERR(( "fd_funkier_txn_prepare() failed" ));
363364
return -1;
364365
}
366+
fd_funkier_txn_end_write( funk );
365367

366368
fd_funkier_txn_t * parent_txn = slot_ctx->funk_txn;
367369
slot_ctx->funk_txn = cache_txn;
368370

371+
fd_funkier_txn_start_read( funk );
369372
fd_funkier_rec_t const * rec = fd_funkier_txn_first_rec( funk, funk_txn );
370373
while( rec!=NULL ) {
371374
FD_SPAD_FRAME_BEGIN( runtime_spad ) {
@@ -402,11 +405,13 @@ fd_bpf_scan_and_create_bpf_program_cache_entry_tpool( fd_exec_slot_ctx_t * slot_
402405

403406
} FD_SPAD_FRAME_END;
404407
}
408+
fd_funkier_txn_start_read( funk );
405409

410+
fd_funkier_txn_start_write( funk );
406411
if( fd_funkier_txn_publish_into_parent( funk, cache_txn, 1 ) != FD_FUNKIER_SUCCESS ) {
407412
FD_LOG_ERR(( "fd_funkier_txn_publish_into_parent() failed" ));
408-
return -1;
409413
}
414+
fd_funkier_txn_end_write( funk );
410415

411416
slot_ctx->funk_txn = parent_txn;
412417

@@ -427,15 +432,18 @@ fd_bpf_scan_and_create_bpf_program_cache_entry( fd_exec_slot_ctx_t * slot_ctx,
427432
/* Use random-ish xid to avoid concurrency issues */
428433
fd_funkier_txn_xid_t cache_xid = fd_funkier_generate_xid();
429434

435+
fd_funkier_txn_start_write( funk );
430436
fd_funkier_txn_t * cache_txn = fd_funkier_txn_prepare( funk, slot_ctx->funk_txn, &cache_xid, 1 );
431437
if( !cache_txn ) {
432438
FD_LOG_ERR(( "fd_funkier_txn_prepare() failed" ));
433439
return -1;
434440
}
441+
fd_funkier_txn_end_write( funk );
435442

436443
fd_funkier_txn_t * parent_txn = slot_ctx->funk_txn;
437444
slot_ctx->funk_txn = cache_txn;
438445

446+
fd_funkier_txn_start_read( funk );
439447
for (fd_funkier_rec_t const *rec = fd_funkier_txn_first_rec( funk, funk_txn );
440448
NULL != rec;
441449
rec = fd_funkier_txn_next_rec( funk, rec )) {
@@ -454,13 +462,16 @@ fd_bpf_scan_and_create_bpf_program_cache_entry( fd_exec_slot_ctx_t * slot_ctx,
454462
cnt++;
455463
}
456464
}
465+
fd_funkier_txn_end_read( funk );
457466

458467
FD_LOG_DEBUG(( "loaded program cache: %lu", cnt));
459468

469+
fd_funkier_txn_start_write( funk );
460470
if( fd_funkier_txn_publish_into_parent( funk, cache_txn, 1 ) != FD_FUNKIER_SUCCESS ) {
461471
FD_LOG_ERR(( "fd_funkier_txn_publish_into_parent() failed" ));
462472
return -1;
463473
}
474+
fd_funkier_txn_end_write( funk );
464475

465476
slot_ctx->funk_txn = parent_txn;
466477
return 0;

src/flamenco/runtime/tests/fd_exec_instr_test.c

+8
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,9 @@ fd_exec_test_instr_context_create( fd_exec_instr_test_runner_t * runner,
371371

372372
/* Create temporary funk transaction and txn / slot / epoch contexts */
373373

374+
fd_funkier_txn_start_write( funk );
374375
fd_funkier_txn_t * funk_txn = fd_funkier_txn_prepare( funk, NULL, xid, 1 );
376+
fd_funkier_txn_end_write( funk );
375377

376378
ulong vote_acct_max = MAX_TX_ACCOUNT_LOCKS;
377379

@@ -732,7 +734,9 @@ _txn_context_create_and_exec( fd_exec_instr_test_runner_t * runner,
732734

733735
/* Create temporary funk transaction and spad contexts */
734736

737+
fd_funkier_txn_start_write( funk );
735738
fd_funkier_txn_t * funk_txn = fd_funkier_txn_prepare( funk, NULL, xid, 1 );
739+
fd_funkier_txn_end_write( funk );
736740

737741
ulong vote_acct_max = MAX_TX_ACCOUNT_LOCKS;
738742

@@ -1001,7 +1005,9 @@ _block_context_create_and_exec( fd_exec_instr_test_runner_t * runner,
10011005
xid[0] = fd_funkier_generate_xid();
10021006

10031007
/* Create temporary funk transaction and slot / epoch contexts */
1008+
fd_funkier_txn_start_write( funk );
10041009
fd_funkier_txn_t * funk_txn = fd_funkier_txn_prepare( funk, NULL, xid, 1 );
1010+
fd_funkier_txn_end_write( funk );
10051011

10061012
/* Allocate contexts */
10071013
ulong vote_acct_max = fd_ulong_max( 128UL,
@@ -1270,7 +1276,9 @@ _block_context_create_and_exec( fd_exec_instr_test_runner_t * runner,
12701276
/* Make a new funk transaction since we're done loading in accounts for context */
12711277
fd_funkier_txn_xid_t fork_xid[1] = {0};
12721278
fork_xid[0] = fd_funkier_generate_xid();
1279+
fd_funkier_txn_start_write( funk );
12731280
slot_ctx->funk_txn = fd_funkier_txn_prepare( funk, slot_ctx->funk_txn, fork_xid, 1 );
1281+
fd_funkier_txn_end_write( funk );
12741282

12751283
/* Calculate epoch account hash values. This sets epoch_bank.eah_{start_slot, stop_slot, interval} */
12761284
fd_calculate_epoch_accounts_hash_values( slot_ctx );

src/flamenco/snapshot/fd_snapshot.c

+4
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ fd_snapshot_load_init( fd_snapshot_load_ctx_t * ctx ) {
144144
incremental_snapshot_only_incremental_hash_calculation ) ) {
145145
fd_funkier_txn_xid_t xid;
146146
memset( &xid, 0xc3, sizeof(xid) );
147+
fd_funkier_txn_start_write( ctx->slot_ctx->acc_mgr->funk );
147148
ctx->child_txn = fd_funkier_txn_prepare( ctx->slot_ctx->acc_mgr->funk, ctx->child_txn, &xid, 0 );
149+
fd_funkier_txn_end_write( ctx->slot_ctx->acc_mgr->funk );
148150
ctx->slot_ctx->funk_txn = ctx->child_txn;
149151
}
150152
}
@@ -287,7 +289,9 @@ fd_snapshot_load_fini( fd_snapshot_load_ctx_t * ctx ) {
287289
}
288290

289291
if( ctx->child_txn != ctx->par_txn ) {
292+
fd_funkier_txn_start_write( ctx->slot_ctx->acc_mgr->funk );
290293
fd_funkier_txn_publish( ctx->slot_ctx->acc_mgr->funk, ctx->child_txn, 0 );
294+
fd_funkier_txn_end_write( ctx->slot_ctx->acc_mgr->funk );
291295
ctx->slot_ctx->funk_txn = ctx->par_txn;
292296
}
293297

src/funkier/fd_funkier_txn.c

+24
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,30 @@
2121
#define MAP_IMPL_STYLE 2
2222
#include "../util/tmpl/fd_map_para.c"
2323

24+
/* TODO: remove this lock */
25+
#include "../flamenco/fd_rwlock.h"
26+
static fd_rwlock_t funkier_txn_lock[ 1 ] = {0};
27+
28+
void
29+
fd_funkier_txn_start_read( fd_funkier_t * funk ) {
30+
fd_rwlock_read( funkier_txn_lock );
31+
}
32+
33+
void
34+
fd_funkier_txn_end_read( fd_funkier_t * funk ) {
35+
fd_rwlock_unread( funkier_txn_lock );
36+
}
37+
38+
void
39+
fd_funkier_txn_start_write( fd_funkier_t * funk ) {
40+
fd_rwlock_write( funkier_txn_lock );
41+
}
42+
43+
void
44+
fd_funkier_txn_end_write( fd_funkier_t * funk ) {
45+
fd_rwlock_unwrite( funkier_txn_lock );
46+
}
47+
2448
fd_funkier_txn_t *
2549
fd_funkier_txn_prepare( fd_funkier_t * funk,
2650
fd_funkier_txn_t * parent,

src/funkier/fd_funkier_txn.h

+36-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,41 @@ static inline int fd_funkier_txn_idx_is_null( ulong idx ) { return idx==FD_FUNKI
8989
/* Generate a globally unique pseudo-random xid */
9090
fd_funkier_txn_xid_t fd_funkier_generate_xid(void);
9191

92+
/* Concurrency control */
93+
94+
/* APIs for marking the start and end of operations that read or write to
95+
the Funkier transactions.
96+
97+
IMPORTANT SAFETY TIP
98+
99+
The following APIs need the write lock:
100+
- fd_funkier_txn_prepare
101+
- fd_funkier_txn_publish
102+
- fd_funkier_txn_publish_into_parent
103+
- fd_funkier_txn_cancel
104+
- fd_funkier_txn_cancel_siblings
105+
- fd_funkier_txn_cancel_children
106+
107+
The following APIs need the read lock:
108+
- fd_funkier_txn_ancestor
109+
- fd_funkier_txn_descendant
110+
- fd_funkier_txn_all_iter
111+
112+
TODO: in future we may be able to make these lock-free, but they are called
113+
infrequently so not sure how much of a gain this would be.
114+
*/
115+
void
116+
fd_funkier_txn_start_read( fd_funkier_t * funk );
117+
118+
void
119+
fd_funkier_txn_end_read( fd_funkier_t * funk );
120+
121+
void
122+
fd_funkier_txn_start_write( fd_funkier_t * funk );
123+
124+
void
125+
fd_funkier_txn_end_write( fd_funkier_t * funk );
126+
92127
/* Accessors */
93128

94129
/* fd_funkier_txn_query returns a pointer to an in-preparation transaction
@@ -107,8 +142,8 @@ fd_funkier_txn_xid_t fd_funkier_generate_xid(void);
107142
FD_FN_PURE static inline fd_funkier_txn_t *
108143
fd_funkier_txn_query( fd_funkier_txn_xid_t const * xid,
109144
fd_funkier_txn_map_t * map ) {
110-
fd_funkier_txn_map_query_t query[1];
111145
do {
146+
fd_funkier_txn_map_query_t query[1];
112147
if( FD_UNLIKELY( fd_funkier_txn_map_query_try( map, xid, NULL, query ) ) ) return NULL;
113148
fd_funkier_txn_t * ele = fd_funkier_txn_map_query_ele( query );
114149
if( FD_LIKELY( !fd_funkier_txn_map_query_test( query ) ) ) return ele;

0 commit comments

Comments
 (0)