Line data Source code
1 : /* fd_solfuzz.c contains support routines */
2 :
3 : #define _GNU_SOURCE
4 : #include "fd_solfuzz.h"
5 : #include "../fd_bank.h"
6 : #include "../fd_runtime.h"
7 : #include <errno.h>
8 : #include <sys/mman.h>
9 : #include "../../../util/shmem/fd_shmem_private.h"
10 :
11 : fd_wksp_t *
12 : fd_wksp_demand_paged_new( char const * name,
13 : uint seed,
14 : ulong part_max,
15 0 : ulong data_max ) {
16 0 : ulong footprint = fd_wksp_footprint( part_max, data_max );
17 0 : if( FD_UNLIKELY( !footprint ) ) {
18 0 : FD_LOG_WARNING(( "invalid workspace params (part_max=%lu data_max=%lu)", part_max, data_max ));
19 0 : return NULL;
20 0 : }
21 :
22 : /* Round up footprint to nearest huge page size */
23 0 : footprint = fd_ulong_align_up( footprint, FD_SHMEM_HUGE_PAGE_SZ );
24 :
25 : /* Acquire anonymous demand-paged memory */
26 0 : void * mem = fd_shmem_private_map_rand( footprint, FD_SHMEM_HUGE_PAGE_SZ, PROT_READ|PROT_WRITE );
27 0 : if( FD_UNLIKELY( mem==MAP_FAILED ) ) {
28 0 : FD_LOG_WARNING(( "fd_shmem_private_map_rand() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
29 0 : return NULL;
30 0 : }
31 :
32 : /* Indicate to kernel that hugepages are a fine backing store
33 : (Transparent Huge Pages) */
34 0 : if( FD_UNLIKELY( 0!=madvise( mem, footprint, MADV_HUGEPAGE ) ) ) {
35 0 : FD_LOG_WARNING(( "madvise() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
36 0 : munmap( mem, footprint );
37 0 : return NULL;
38 0 : }
39 :
40 : /* Create workspace */
41 0 : fd_wksp_t * wksp = fd_wksp_join( fd_wksp_new( mem, name, seed, part_max, data_max ) );
42 0 : if( FD_UNLIKELY( !wksp ) ) {
43 0 : FD_LOG_WARNING(( "fd_wksp_new() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
44 0 : munmap( mem, footprint );
45 0 : return NULL;
46 0 : }
47 :
48 : /* Register shared memory region */
49 0 : ulong fake_page_cnt = footprint>>FD_SHMEM_HUGE_LG_PAGE_SZ;
50 0 : int join_err = fd_shmem_join_anonymous(
51 0 : name,
52 0 : FD_SHMEM_JOIN_MODE_READ_WRITE,
53 0 : wksp,
54 0 : mem,
55 0 : FD_SHMEM_HUGE_PAGE_SZ,
56 0 : fake_page_cnt
57 0 : );
58 0 : if( FD_UNLIKELY( join_err ) ) {
59 0 : FD_LOG_WARNING(( "fd_shmem_join_anonymous() failed (%i-%s)", join_err, fd_io_strerror( join_err ) ));
60 0 : fd_wksp_delete( fd_wksp_leave( wksp ) );
61 0 : munmap( mem, footprint );
62 0 : return NULL;
63 0 : }
64 :
65 0 : return wksp;
66 0 : }
67 :
68 : void
69 0 : fd_wksp_demand_paged_delete( fd_wksp_t * wksp ) {
70 0 : fd_shmem_leave_anonymous( wksp, NULL );
71 0 : FD_TEST( fd_wksp_delete( fd_wksp_leave( wksp ) ) );
72 0 : }
73 :
74 : fd_solfuzz_runner_t *
75 : fd_solfuzz_runner_new( fd_wksp_t * wksp,
76 : ulong wksp_tag,
77 0 : fd_solfuzz_runner_options_t const * options ) {
78 :
79 : /* Allocate objects */
80 0 : ulong const txn_max = 64UL;
81 0 : ulong const rec_max = 1024UL;
82 0 : ulong const spad_max = FD_RUNTIME_TRANSACTION_EXECUTION_FOOTPRINT_FUZZ;
83 0 : ulong const bank_max = 1UL;
84 0 : ulong const fork_max = 1UL;
85 0 : fd_solfuzz_runner_t * runner = fd_wksp_alloc_laddr( wksp, alignof(fd_solfuzz_runner_t), sizeof(fd_solfuzz_runner_t), wksp_tag );
86 0 : void * funk_mem = fd_wksp_alloc_laddr( wksp, fd_funk_align(), fd_funk_footprint( txn_max, rec_max ), wksp_tag );
87 0 : void * spad_mem = fd_wksp_alloc_laddr( wksp, fd_spad_align(), fd_spad_footprint( spad_max ), wksp_tag );
88 0 : void * banks_mem = fd_wksp_alloc_laddr( wksp, fd_banks_align(), fd_banks_footprint( bank_max, fork_max ), wksp_tag );
89 0 : if( FD_UNLIKELY( !runner ) ) { FD_LOG_WARNING(( "fd_wksp_alloc(solfuzz_runner) failed" )); goto bail1; }
90 0 : if( FD_UNLIKELY( !funk_mem ) ) { FD_LOG_WARNING(( "fd_wksp_alloc(funk) failed" )); goto bail1; }
91 0 : if( FD_UNLIKELY( !spad_mem ) ) { FD_LOG_WARNING(( "fd_wksp_alloc(spad) failed (spad_max=%g)", (double)spad_max )); goto bail1; }
92 0 : if( FD_UNLIKELY( !banks_mem ) ) { FD_LOG_WARNING(( "fd_wksp_alloc(banks) failed (bank_max=%lu fork_max=%lu)", bank_max, fork_max )); goto bail1; }
93 :
94 : /* Create objects */
95 0 : fd_memset( runner, 0, sizeof(fd_solfuzz_runner_t) );
96 0 : runner->wksp = wksp;
97 0 : void * shfunk = fd_funk_new( funk_mem, wksp_tag, 1UL, txn_max, rec_max );
98 0 : if( FD_UNLIKELY( !shfunk ) ) goto bail1;
99 0 : if( FD_UNLIKELY( !fd_funk_join( runner->funk, funk_mem ) ) ) goto bail2;
100 0 : runner->spad = fd_spad_join( fd_spad_new( spad_mem, spad_max ) );
101 0 : if( FD_UNLIKELY( !runner->spad ) ) goto bail2;
102 0 : runner->banks = fd_banks_join( fd_banks_new( banks_mem, bank_max, fork_max ) );
103 0 : if( FD_UNLIKELY( !runner->banks ) ) goto bail2;
104 0 : runner->bank = fd_banks_init_bank( runner->banks, fd_eslot( 0UL, 0UL ) );
105 0 : if( FD_UNLIKELY( !runner->bank ) ) {
106 0 : FD_LOG_WARNING(( "fd_banks_init_bank failed" ));
107 0 : goto bail2;
108 0 : }
109 :
110 0 : runner->enable_vm_tracing = options->enable_vm_tracing;
111 0 : return runner;
112 :
113 0 : bail2:
114 0 : if( runner->spad ) fd_spad_delete( fd_spad_leave( runner->spad ) );
115 0 : if( shfunk ) fd_funk_delete( funk_mem ); /* free underlying fd_alloc instance */
116 0 : if( runner->banks ) fd_banks_delete( fd_banks_leave( runner->banks ) );
117 0 : bail1:
118 0 : fd_wksp_free_laddr( funk_mem );
119 0 : fd_wksp_free_laddr( spad_mem );
120 0 : fd_wksp_free_laddr( banks_mem );
121 0 : fd_wksp_free_laddr( runner );
122 0 : FD_LOG_WARNING(( "fd_solfuzz_runner_new failed" ));
123 0 : return NULL;
124 0 : }
125 :
126 : void
127 0 : fd_solfuzz_runner_delete( fd_solfuzz_runner_t * runner ) {
128 0 : void * shfunk = NULL;
129 0 : fd_funk_leave( runner->funk, &shfunk );
130 0 : if( shfunk ) fd_wksp_free_laddr( fd_funk_delete( shfunk ) );
131 0 : if( runner->spad ) fd_wksp_free_laddr( fd_spad_delete( fd_spad_leave( runner->spad ) ) );
132 0 : if( runner->banks ) fd_wksp_free_laddr( fd_banks_delete( fd_banks_leave( runner->banks ) ) );
133 0 : fd_wksp_free_laddr( runner );
134 0 : }
135 :
136 : void
137 0 : fd_solfuzz_runner_leak_check( fd_solfuzz_runner_t * runner ) {
138 0 : if( FD_UNLIKELY( fd_spad_frame_used( runner->spad ) ) ) {
139 0 : FD_LOG_CRIT(( "solfuzz leaked a spad frame (bump allocator)" ));
140 0 : }
141 :
142 0 : fd_funk_txn_all_iter_t iter[1];
143 0 : for( fd_funk_txn_all_iter_new( runner->funk, iter ); !fd_funk_txn_all_iter_done( iter ); fd_funk_txn_all_iter_next( iter ) ) {
144 0 : FD_LOG_CRIT(( "solfuzz leaked a funk txn" ));
145 0 : }
146 0 : }
|