Line data Source code
1 : #include "fd_forks.h"
2 :
3 : #include "../../flamenco/runtime/context/fd_exec_slot_ctx.h"
4 : #include "../../flamenco/runtime/fd_acc_mgr.h"
5 : #include "../../flamenco/runtime/fd_borrowed_account.h"
6 : #include "../../flamenco/runtime/fd_runtime.h"
7 : #include "../../flamenco/runtime/program/fd_program_util.h"
8 : #include "../../flamenco/runtime/program/fd_vote_program.h"
9 :
10 : void *
11 0 : fd_forks_new( void * shmem, ulong max, ulong seed ) {
12 :
13 0 : if( FD_UNLIKELY( !shmem ) ) {
14 0 : FD_LOG_WARNING( ( "NULL mem" ) );
15 0 : return NULL;
16 0 : }
17 :
18 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_forks_align() ) ) ) {
19 0 : FD_LOG_WARNING( ( "misaligned mem" ) );
20 0 : return NULL;
21 0 : }
22 :
23 0 : ulong footprint = fd_forks_footprint( max );
24 0 : if( FD_UNLIKELY( !footprint ) ) {
25 0 : FD_LOG_WARNING( ( "bad mem" ) );
26 0 : return NULL;
27 0 : }
28 :
29 0 : fd_memset( shmem, 0, footprint );
30 0 : ulong laddr = (ulong)shmem;
31 :
32 0 : laddr = fd_ulong_align_up( laddr, alignof( fd_forks_t ) );
33 0 : laddr += sizeof( fd_forks_t );
34 :
35 0 : laddr = fd_ulong_align_up( laddr, fd_fork_pool_align() );
36 0 : fd_fork_pool_new( (void *)laddr, max );
37 0 : laddr += fd_fork_pool_footprint( max );
38 :
39 0 : laddr = fd_ulong_align_up( laddr, fd_fork_frontier_align() );
40 0 : fd_fork_frontier_new( (void *)laddr, max, seed );
41 0 : laddr += fd_fork_frontier_footprint( max );
42 :
43 0 : return shmem;
44 0 : }
45 :
46 : fd_forks_t *
47 0 : fd_forks_join( void * shforks ) {
48 :
49 0 : if( FD_UNLIKELY( !shforks ) ) {
50 0 : FD_LOG_WARNING( ( "NULL forks" ) );
51 0 : return NULL;
52 0 : }
53 :
54 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shforks, fd_forks_align() ) ) ) {
55 0 : FD_LOG_WARNING( ( "misaligned forks" ) );
56 0 : return NULL;
57 0 : }
58 :
59 0 : ulong laddr = (ulong)shforks;
60 0 : fd_forks_t * forks = (void *)laddr;
61 :
62 0 : laddr = fd_ulong_align_up( laddr, alignof( fd_forks_t ) );
63 0 : laddr += sizeof( fd_forks_t );
64 :
65 0 : laddr = fd_ulong_align_up( laddr, fd_fork_pool_align() );
66 0 : forks->pool = fd_fork_pool_join( (void *)laddr );
67 0 : ulong max = fd_fork_pool_max( forks->pool );
68 0 : laddr += fd_fork_pool_footprint( max );
69 :
70 0 : laddr = fd_ulong_align_up( laddr, fd_fork_frontier_align() );
71 0 : forks->frontier = fd_fork_frontier_join( (void *)laddr );
72 0 : laddr += fd_fork_frontier_footprint( max );
73 :
74 0 : return (fd_forks_t *)shforks;
75 0 : }
76 :
77 : void *
78 0 : fd_forks_leave( fd_forks_t const * forks ) {
79 :
80 0 : if( FD_UNLIKELY( !forks ) ) {
81 0 : FD_LOG_WARNING( ( "NULL forks" ) );
82 0 : return NULL;
83 0 : }
84 :
85 0 : return (void *)forks;
86 0 : }
87 :
88 : void *
89 0 : fd_forks_delete( void * forks ) {
90 :
91 0 : if( FD_UNLIKELY( !forks ) ) {
92 0 : FD_LOG_WARNING( ( "NULL forks" ) );
93 0 : return NULL;
94 0 : }
95 :
96 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)forks, fd_forks_align() ) ) ) {
97 0 : FD_LOG_WARNING( ( "misaligned forks" ) );
98 0 : return NULL;
99 0 : }
100 :
101 0 : return forks;
102 0 : }
103 :
104 : fd_fork_t *
105 0 : fd_forks_init( fd_forks_t * forks, ulong slot ) {
106 :
107 0 : if( FD_UNLIKELY( !forks ) ) {
108 0 : FD_LOG_WARNING( ( "NULL forks" ) );
109 0 : return NULL;
110 0 : }
111 :
112 0 : fd_fork_t * fork = fd_fork_pool_ele_acquire( forks->pool );
113 0 : fork->slot = slot;
114 0 : fork->prev = fd_fork_pool_idx_null( forks->pool );
115 0 : fork->lock = 0;
116 0 : if( FD_UNLIKELY( !fd_fork_frontier_ele_insert( forks->frontier, fork, forks->pool ) ) ) {
117 0 : FD_LOG_WARNING( ( "Failed to insert fork into frontier" ) );
118 0 : }
119 :
120 0 : return fork;
121 0 : }
122 :
123 : fd_fork_t *
124 0 : fd_forks_query( fd_forks_t * forks, ulong slot ) {
125 0 : return fd_fork_frontier_ele_query( forks->frontier, &slot, NULL, forks->pool );
126 0 : }
127 :
128 : fd_fork_t const *
129 0 : fd_forks_query_const( fd_forks_t const * forks, ulong slot ) {
130 0 : return fd_fork_frontier_ele_query_const( forks->frontier, &slot, NULL, forks->pool );
131 0 : }
132 :
133 : // fd_fork_t *
134 : // fd_forks_advance( fd_forks_t * forks,
135 : // fd_fork_t * fork,
136 : // ulong slot,
137 : // fd_funk_t * funk,
138 : // fd_blockstore_t * blockstore,
139 : // fd_funk_t * funk,
140 : // fd_valloc_t valloc ) {
141 : // // Remove slot ctx from frontier
142 : // fd_fork_t * child = fd_fork_frontier_ele_remove( forks->frontier,
143 : // &fork->slot,
144 : // NULL,
145 : // forks->pool );
146 : // child->slot = curr_slot;
147 : // if( FD_UNLIKELY( fd_fork_frontier_ele_query( forks->frontier,
148 : // &curr_slot,
149 : // NULL,
150 : // forks->pool ) ) ) {
151 : // FD_LOG_ERR( ( "invariant violation: child slot %lu was already in the
152 : // frontier", curr_slot ) );
153 : // }
154 : // fd_fork_frontier_ele_insert( forks->frontier, child, forks->pool );
155 : // FD_TEST( fork == child );
156 :
157 : // // fork is advancing
158 : // FD_LOG_DEBUG(( "new block execution - slot: %lu, parent_slot: %lu", curr_slot, parent_slot ));
159 :
160 : // fork->slot_ctx.status_cache = status_cache;
161 : // fd_funk_txn_xid_t xid;
162 :
163 : // fd_memcpy( xid.uc, blockhash.uc, sizeof( fd_funk_txn_xid_t));
164 : // xid.ul[0] = fork->slot_ctx.slot_bank.slot;
165 : // /* push a new transaction on the stack */
166 : // fd_funk_start_write( funk );
167 : // fork->slot_ctx.funk_txn = fd_funk_txn_prepare( funk, fork->slot_ctx.funk_txn, &xid, 1 );
168 : // fd_funk_end_write( funk );
169 :
170 : // int res = fd_runtime_publish_old_txns( &fork->slot_ctx, capture_ctx );
171 : // if( res != FD_RUNTIME_EXECUTE_SUCCESS ) {
172 : // FD_LOG_ERR(( "txn publishing failed" ));
173 : // }
174 : // }
175 :
176 : fd_fork_t *
177 0 : fd_forks_prepare( fd_forks_t const * forks, ulong parent_slot ) {
178 :
179 : /* Query for parent_slot in the frontier. */
180 :
181 0 : fd_fork_t * fork = fd_fork_frontier_ele_query( forks->frontier, &parent_slot, NULL, forks->pool );
182 :
183 : /* If the parent block is both present and executed, but isn't in the
184 : frontier, that means this block is starting a new fork and needs to
185 : be added to the frontier. This requires recovering the slot_ctx
186 : as of that parent_slot by executing a funky rollback. */
187 :
188 0 : if( FD_UNLIKELY( !fork ) ) {
189 :
190 : /* Alloc a new slot_ctx */
191 :
192 0 : fork = fd_fork_pool_ele_acquire( forks->pool );
193 0 : fork->prev = fd_fork_pool_idx_null( forks->pool );
194 0 : fork->slot = parent_slot;
195 0 : fork->lock = 1;
196 :
197 : /* Add to frontier */
198 :
199 0 : fd_fork_frontier_ele_insert( forks->frontier, fork, forks->pool );
200 0 : }
201 :
202 0 : return fork;
203 0 : }
204 :
205 : void
206 0 : fd_forks_publish( fd_forks_t * forks, ulong slot ) {
207 0 : fd_fork_t * tail = NULL;
208 0 : fd_fork_t * curr = NULL;
209 :
210 0 : for( fd_fork_frontier_iter_t iter = fd_fork_frontier_iter_init( forks->frontier, forks->pool );
211 0 : !fd_fork_frontier_iter_done( iter, forks->frontier, forks->pool );
212 0 : iter = fd_fork_frontier_iter_next( iter, forks->frontier, forks->pool ) ) {
213 0 : fd_fork_t * fork = fd_fork_frontier_iter_ele( iter, forks->frontier, forks->pool );
214 :
215 : /* Prune any forks not in the ancestry from root.
216 :
217 : Optimize for unlikely because there is usually just one fork. */
218 :
219 0 : if( FD_UNLIKELY( !fork->lock && fork->slot < slot ) ) {
220 0 : if( FD_LIKELY( !curr ) ) {
221 0 : tail = fork;
222 0 : curr = fork;
223 0 : } else {
224 0 : curr->prev = fd_fork_pool_idx( forks->pool, fork );
225 0 : curr = fd_fork_pool_ele( forks->pool, curr->prev );
226 0 : }
227 0 : }
228 0 : }
229 :
230 0 : while( FD_UNLIKELY( tail ) ) {
231 0 : ulong remove = fd_fork_frontier_idx_remove( forks->frontier,
232 0 : &tail->slot,
233 0 : fd_fork_pool_idx_null( forks->pool ),
234 0 : forks->pool );
235 0 : #if FD_FORKS_USE_HANDHOLDING
236 0 : if( FD_UNLIKELY( remove == fd_fork_pool_idx_null( forks->pool ) ) ) {
237 0 : FD_LOG_ERR( ( "failed to remove fork we added to prune." ) );
238 0 : }
239 0 : #endif
240 :
241 : /* pool_idx_release cannot fail given we just removed this from the
242 : frontier directly above. */
243 0 : fd_fork_pool_idx_release( forks->pool, remove );
244 0 : tail = fd_ptr_if( tail->prev != fd_fork_pool_idx_null( forks->pool ),
245 0 : fd_fork_pool_ele( forks->pool, tail->prev ),
246 0 : NULL );
247 0 : }
248 0 : }
249 :
250 : #include <stdio.h>
251 :
252 : void
253 0 : fd_forks_print( fd_forks_t const * forks ) {
254 0 : FD_LOG_NOTICE( ( "\n\n[Forks]" ) );
255 0 : for( fd_fork_frontier_iter_t iter = fd_fork_frontier_iter_init( forks->frontier, forks->pool );
256 0 : !fd_fork_frontier_iter_done( iter, forks->frontier, forks->pool );
257 0 : iter = fd_fork_frontier_iter_next( iter, forks->frontier, forks->pool ) ) {
258 0 : printf( "%lu\n", fd_fork_frontier_iter_ele_const( iter, forks->frontier, forks->pool )->slot );
259 0 : }
260 : printf( "\n" );
261 0 : }
|