Skip to content

Commit 3442a8e

Browse files
committed
utils,spad: add spad handholding
1 parent 6dbb69e commit 3442a8e

File tree

10 files changed

+147
-13
lines changed

10 files changed

+147
-13
lines changed

src/discof/rpcserver/fd_methods.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ void json_add_value(struct json_values* values, struct json_path* path, const vo
192192
values->buf_alloc <<= 1;
193193
} while (new_buf_sz > values->buf_alloc);
194194
char* newbuf = (char*)fd_spad_alloc( spad, 1, values->buf_alloc);
195+
if ( FD_UNLIKELY( NULL == newbuf ) ) {
196+
FD_LOG_ERR(( "out of spad scratch space" ));
197+
}
195198
fd_memcpy(newbuf, values->buf, values->buf_sz);
196199
values->buf = newbuf;
197200
}

src/discof/rpcserver/fd_rpc_history.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ fd_rpc_history_t *
9292
fd_rpc_history_create(fd_rpcserver_args_t * args) {
9393
fd_spad_t * spad = args->spad;
9494
fd_rpc_history_t * hist = (fd_rpc_history_t *)fd_spad_alloc( spad, alignof(fd_rpc_history_t), sizeof(fd_rpc_history_t) );
95+
if ( FD_UNLIKELY ( NULL == hist ) ) {
96+
FD_LOG_ERR(( "out of spad scratch space" ));
97+
}
9598
memset(hist, 0, sizeof(fd_rpc_history_t));
9699
hist->spad = spad;
97100

src/discof/rpcserver/json_lex.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ static char* json_lex_append_prepare(json_lex_state_t* lex, ulong sz) {
387387
} while (new_sz + 1 > lex->last_str_alloc);
388388
char* oldstr = lex->last_str;
389389
lex->last_str = (char*)fd_spad_alloc( lex->spad, 1, lex->last_str_alloc);
390+
if ( FD_UNLIKELY ( NULL == lex->last_str ) ) {
391+
// TODO: what should we do?
392+
return NULL;
393+
}
390394
// Copy the old content to the new space
391395
fd_memcpy(lex->last_str, oldstr, lex->last_str_sz);
392396
}

src/flamenco/runtime/fd_executor.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,9 @@ fd_executor_create_rollback_fee_payer_account( fd_exec_txn_ctx_t * txn_ctx,
919919

920920
ulong data_len = fd_txn_account_get_data_len( &txn_ctx->accounts[FD_FEE_PAYER_TXN_IDX] );
921921
void * fee_payer_data = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, sizeof(fd_account_meta_t) + data_len );
922+
if( FD_UNLIKELY( NULL == fee_payer_data ) ) {
923+
FD_LOG_CRIT(( "out of spad scratch space" ));
924+
}
922925
fd_memcpy( fee_payer_data, (uchar *)meta, sizeof(fd_account_meta_t) + data_len );
923926
if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new(
924927
txn_ctx->rollback_fee_payer_account,
@@ -1408,6 +1411,9 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx,
14081411
initialize a new metadata. */
14091412

14101413
uchar * new_raw_data = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, FD_ACC_TOT_SZ_MAX );
1414+
if( FD_UNLIKELY( NULL == new_raw_data ) ) {
1415+
FD_LOG_CRIT(( "out of spad scratch space" ));
1416+
}
14111417
ulong dlen = !!meta ? meta->dlen : 0UL;
14121418

14131419
if( FD_LIKELY( meta ) ) {
@@ -1432,6 +1438,9 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx,
14321438
data_wksp = fd_funk_wksp( txn_ctx->funk );
14331439
} else {
14341440
uchar * mem = fd_spad_alloc( txn_ctx->spad, FD_TXN_ACCOUNT_ALIGN, sizeof(fd_account_meta_t) );
1441+
if( FD_UNLIKELY( NULL == mem ) ) {
1442+
FD_LOG_CRIT(( "out of spad scratch space" ));
1443+
}
14351444
account_meta = (fd_account_meta_t *)mem;
14361445
data_wksp = txn_ctx->spad_wksp;
14371446
fd_account_meta_init( account_meta );

src/flamenco/runtime/fd_txncache.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,9 @@ fd_txncache_get_entries( fd_txncache_t * tc,
10641064

10651065
status_pair->value.statuses_len = num_statuses;
10661066
status_pair->value.statuses = fd_spad_alloc( spad, FD_CACHE_STATUS_ALIGN, num_statuses * sizeof(fd_cache_status_t) );
1067+
if( FD_UNLIKELY( NULL == status_pair->value.statuses )) {
1068+
FD_LOG_CRIT(( "out of spad scratch space" ));
1069+
}
10671070
fd_memset( status_pair->value.statuses, 0, num_statuses * sizeof(fd_cache_status_t) );
10681071

10691072
/* Copy over every entry for the given slot into the slot deltas. */

src/flamenco/runtime/program/fd_system_program.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
static inline char *
2121
fd_log_address_type( fd_spad_t * spad, fd_pubkey_t const * pubkey, fd_pubkey_t const * base ) {
2222
char * out = fd_spad_alloc( spad, alignof(char), 125UL );
23+
if ( FD_UNLIKELY ( NULL == out ) ) {
24+
FD_LOG_ERR(( "out of spad scratch spaced during logging" ));
25+
}
2326
char base_addr[52];
2427
if( FD_UNLIKELY( base ) ) {
2528
snprintf( base_addr, 52UL, "Some(%s)", FD_BASE58_ENC_32_ALLOCA( base ) );

src/flamenco/runtime/tests/fd_dump_pb.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ dump_vote_accounts( fd_exec_slot_ctx_t const * slot_ctx,
201201
fd_exec_test_vote_account_t * vote_account_out = fd_spad_alloc( spad,
202202
alignof(fd_exec_test_vote_account_t),
203203
vote_account_t_cnt * sizeof(fd_exec_test_vote_account_t) );
204+
if( FD_UNLIKELY( NULL == vote_account_out ) ) {
205+
FD_LOG_CRIT(( "out of spad scratch space" ));
206+
}
204207

205208
for( fd_vote_accounts_pair_global_t_mapnode_t const * curr = fd_vote_accounts_pair_global_t_map_minimum_const(
206209
vote_accounts_pool,
@@ -1041,6 +1044,10 @@ fd_dump_block_to_protobuf_tx_only( fd_runtime_block_info_t const * block_info,
10411044
/* Output to file */
10421045
ulong out_buf_size = 5UL<<30UL; /* 5 GB */
10431046
uint8_t * out = fd_spad_alloc( spad, alignof(uint8_t), out_buf_size );
1047+
if( FD_UNLIKELY( NULL == out ) ) {
1048+
FD_LOG_CRIT(( "out of spad scratch space" ));
1049+
}
1050+
10441051
pb_ostream_t stream = pb_ostream_from_buffer( out, out_buf_size );
10451052
if( pb_encode( &stream, FD_EXEC_TEST_BLOCK_CONTEXT_FIELDS, block_context_msg ) ) {
10461053
char output_filepath[256]; fd_memset( output_filepath, 0, sizeof(output_filepath) );
@@ -1227,6 +1234,9 @@ FD_SPAD_FRAME_BEGIN( txn_ctx->spad ) {
12271234
/* Output to file */
12281235
ulong out_buf_size = 1UL<<29UL; /* 128 MB */
12291236
uint8_t * out = fd_spad_alloc( txn_ctx->spad, alignof(uint8_t), out_buf_size );
1237+
if( FD_UNLIKELY( NULL == out ) ) {
1238+
FD_LOG_CRIT(( "out of spad scratch space" ));
1239+
}
12301240
pb_ostream_t stream = pb_ostream_from_buffer( out, out_buf_size );
12311241
if( pb_encode( &stream, FD_EXEC_TEST_ELF_LOADER_CTX_FIELDS, &elf_ctx ) ) {
12321242
FILE * file = fopen(filename, "wb");

src/util/log/fd_log.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@
266266

267267
#define FD_TEST_CUSTOM(c,err) do { if( FD_UNLIKELY( !(c) ) ) FD_LOG_ERR(( "FAIL: %s", (err) )); } while(0)
268268

269+
/* FD_TEST_BRK is like FD_TEST but drops into a debugger on failure. */
270+
271+
#define FD_TEST_BRK(c) do { if( FD_UNLIKELY( !(c) ) ) FD_LOG_WARNING(( "FAIL: %s", #c )); __asm__("int $3"); } while(0)
272+
273+
269274
/* Macros for doing hexedit / tcpdump-like logging of memory regions.
270275
E.g.
271276

src/util/spad/fd_spad.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,17 @@ fd_spad_frame_hi_debug( fd_spad_t * spad ) {
6969
return SELECT_DEBUG_IMPL(fd_spad_frame_hi)( spad );
7070
}
7171

72-
void
72+
fd_spad_debug_state_t
7373
fd_spad_push_debug( fd_spad_t * spad ) {
74+
fd_spad_debug_state_t state;
75+
state.frame_free = spad->frame_free;
76+
state.mem_used = spad->mem_used;
77+
state.spad = spad;
78+
7479
if( FD_UNLIKELY( !fd_spad_frame_free( spad ) ) ) FD_LOG_CRIT(( "too many frames" ));
7580
SELECT_DEBUG_IMPL(fd_spad_push)( spad );
81+
82+
return state;
7683
}
7784

7885
void
@@ -81,17 +88,6 @@ fd_spad_pop_debug( fd_spad_t * spad ) {
8188
SELECT_DEBUG_IMPL(fd_spad_pop)( spad );
8289
}
8390

84-
void *
85-
fd_spad_alloc_check( fd_spad_t * spad,
86-
ulong align,
87-
ulong sz ) {
88-
if( FD_UNLIKELY( !fd_spad_frame_used( spad ) ) ) FD_LOG_CRIT(( "not in a frame" ));
89-
if( FD_UNLIKELY( (!!align) & (!fd_ulong_is_pow2( align ) ) ) ) FD_LOG_CRIT(( "bad align" ));
90-
ulong alloc_max = fd_spad_alloc_max( spad, align );
91-
if( FD_UNLIKELY( alloc_max<sz ) ) FD_LOG_CRIT(( "out of memory: attempted to allocate %lu bytes, but only %lu available", sz, alloc_max ));
92-
return SELECT_DEBUG_IMPL(fd_spad_alloc)( spad, align, sz );
93-
}
94-
9591
void
9692
fd_spad_trim_debug( fd_spad_t * spad,
9793
void * hi ) {
@@ -314,3 +310,17 @@ fd_spad_vtable = {
314310
.malloc = fd_spad_valloc_malloc,
315311
.free = fd_spad_valloc_free
316312
};
313+
314+
void
315+
fd_spad_private_frame_end_debug( fd_spad_debug_state_t * _spad_state ) {
316+
fd_spad_pop( _spad_state->spad );
317+
318+
if(_spad_state->frame_free != _spad_state->spad->frame_free ) {
319+
FD_LOG_WARNING(("%lu != %lu", _spad_state->frame_free, _spad_state->spad->frame_free));
320+
FD_TEST_BRK( _spad_state->frame_free == _spad_state->spad->frame_free );
321+
}
322+
if( _spad_state->mem_used != _spad_state->spad->mem_used ) {
323+
FD_LOG_WARNING(("%lu != %lu", _spad_state->mem_used, _spad_state->spad->mem_used));
324+
FD_TEST_BRK( _spad_state->mem_used == _spad_state->spad->mem_used );
325+
}
326+
}

src/util/spad/fd_spad.h

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "../bits/fd_bits.h"
3232
#include "../valloc/fd_valloc.h" // For valloc wrapper interface
33+
#include "../log/fd_log.h"
3334

3435
/* FD_SPAD_{ALIGN,FOOTPRINT} give the alignment and footprint of a
3536
fd_spad_t. ALIGN is an integer power of 2. FOOTPRINT is a multiple
@@ -93,6 +94,13 @@ FD_STATIC_ASSERT( FD_SPAD_ALLOC_ALIGN_DEFAULT >= FD_MSAN_ALIGN,
9394

9495
/* spad internals */
9596

97+
struct fd_spad_debug_state {
98+
ulong frame_free; /* number of frames free, in [0,FD_SPAD_FRAME_MAX] */
99+
ulong mem_used; /* number of spad memory bytes used, in [0,mem_max] */
100+
fd_spad_t *spad;
101+
};
102+
typedef struct fd_spad_debug_state fd_spad_debug_state_t;
103+
96104
struct __attribute__((aligned(FD_SPAD_ALIGN))) fd_spad_private {
97105

98106
/* This point is FD_SPAD_ALIGN aligned */
@@ -360,13 +368,29 @@ fd_spad_private_frame_end( fd_spad_t ** _spad ) { /* declared here to avoid a fd
360368
fd_spad_pop( *_spad );
361369
}
362370

371+
void fd_spad_private_frame_end_debug( fd_spad_debug_state_t * _spad_state);
372+
373+
#if defined(FD_SPAD_USE_HANDHOLDING)
374+
375+
#define FD_SPAD_FRAME_BEGIN(spad) do { \
376+
__attribute__((cleanup(fd_spad_private_frame_end_debug))) fd_spad_debug_state_t _spad_state; \
377+
_spad_state = fd_spad_push_debug( spad ); \
378+
do
379+
380+
#define FD_SPAD_FRAME_END while(0); } while(0)
381+
382+
#else
383+
363384
#define FD_SPAD_FRAME_BEGIN(spad) do { \
364385
fd_spad_t * _spad __attribute__((cleanup(fd_spad_private_frame_end))) = (spad); \
365386
fd_spad_push( _spad ); \
366387
do
367388

368389
#define FD_SPAD_FRAME_END while(0); } while(0)
369390

391+
#endif
392+
393+
370394
/* fd_spad_alloc allocates sz bytes with alignment align from spad.
371395
Returns a pointer in the caller's address space to the first byte of
372396
the allocation (will be non-NULL with alignment align). Assumes spad
@@ -387,6 +411,40 @@ fd_spad_alloc( fd_spad_t * spad,
387411
ulong align,
388412
ulong sz );
389413

414+
/* fd_spad_check confirms you can allocates sz bytes with alignment align
415+
from spad.
416+
*/
417+
418+
static inline int
419+
fd_spad_check( fd_spad_t * spad,
420+
ulong align,
421+
ulong sz );
422+
423+
/* fd_spad_alloc_check allocates sz bytes with alignment align from spad.
424+
Returns a pointer in the caller's address space to the first byte of
425+
the allocation (will be non-NULL with alignment align). Assumes spad
426+
is a current local join and in a frame, align is an integer power of
427+
2 in [1,FD_SPAD_ALIGN] or 0 (indicates to use
428+
FD_SPAD_ALLOC_ALIGN_DEFAULT) and sz is in [0,alloc_max]. Implicitly
429+
cancels any in progress prepare. On return, spad will be in a frame
430+
and not in a prepare. Fast O(1).
431+
432+
The lifetime of the returned region will be until the next pop or
433+
delete and of the returned pointer until pop, delete or leave. The
434+
allocated region will be in the region backing the spad (e.g. if the
435+
spad is backed by wksp memory, the returned value will be a laddr
436+
that can be shared with threads in other processes using that wksp).
437+
438+
Additonal checks are introduced that will cause it to return NULL
439+
if the total size of the spad object have been exceeded or it has
440+
run out of frame space.
441+
*/
442+
443+
static inline void *
444+
fd_spad_alloc_check( fd_spad_t * spad,
445+
ulong align,
446+
ulong sz );
447+
390448
/* fd_spad_trim trims trims frame_hi to end at hi where hi is given the
391449
caller's local address space. Assumes spad is a current local join
392450
in a frame and hi is in [frame_lo,frame_hi] (FIXME: consider
@@ -492,7 +550,7 @@ void * fd_spad_delete_debug ( void * shspad
492550
ulong fd_spad_alloc_max_debug( fd_spad_t const * spad, ulong align );
493551
void * fd_spad_frame_lo_debug ( fd_spad_t * spad );
494552
void * fd_spad_frame_hi_debug ( fd_spad_t * spad );
495-
void fd_spad_push_debug ( fd_spad_t * spad );
553+
fd_spad_debug_state_t fd_spad_push_debug ( fd_spad_t * spad );
496554
void fd_spad_pop_debug ( fd_spad_t * spad );
497555
void * fd_spad_alloc_check ( fd_spad_t * spad, ulong align, ulong sz );
498556
#define fd_spad_alloc_debug fd_spad_alloc_check
@@ -677,6 +735,32 @@ fd_spad_alloc( fd_spad_t * spad,
677735
return SELECT_IMPL(fd_spad_alloc)(spad, align, sz);
678736
}
679737

738+
int
739+
fd_spad_check( fd_spad_t * spad,
740+
ulong align,
741+
ulong sz ) {
742+
743+
if( FD_UNLIKELY( ( !fd_spad_frame_used( spad ) ) |
744+
( (!!align) & (!fd_ulong_is_pow2( align ) ) ) |
745+
( fd_spad_alloc_max( spad, align )<sz )
746+
) ) return 0;
747+
748+
return 1;
749+
}
750+
751+
void *
752+
fd_spad_alloc_check( fd_spad_t * spad,
753+
ulong align,
754+
ulong sz ) {
755+
756+
if( FD_UNLIKELY( ( !fd_spad_frame_used( spad ) ) |
757+
( (!!align) & (!fd_ulong_is_pow2( align ) ) ) |
758+
( fd_spad_alloc_max( spad, align )<sz )
759+
) ) return NULL;
760+
761+
return SELECT_IMPL(fd_spad_alloc)(spad, align, sz);
762+
}
763+
680764
void
681765
fd_spad_trim( fd_spad_t * spad,
682766
void * hi ) {

0 commit comments

Comments
 (0)