LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_borrowed_account.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 39 58 67.2 %
Date: 2025-01-08 12:08:44 Functions: 20 888 2.3 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_fd_borrowed_account_h
       2             : #define HEADER_fd_src_flamenco_runtime_fd_borrowed_account_h
       3             : 
       4             : #include "../../ballet/txn/fd_txn.h"
       5             : #include "../types/fd_types.h"
       6             : #include "../../funk/fd_funk_rec.h"
       7             : 
       8             : 
       9             : /* TODO This should be called fd_txn_acct. */
      10             : 
      11             : struct __attribute__((aligned(8UL))) fd_borrowed_account {
      12             :   ulong                       magic;
      13             : 
      14             :   fd_pubkey_t                 pubkey[1];
      15             : 
      16             :   fd_account_meta_t const   * const_meta;
      17             :   uchar             const   * const_data;
      18             :   fd_funk_rec_t     const   * const_rec;
      19             : 
      20             :   fd_account_meta_t         * meta;
      21             :   uchar                     * data;
      22             :   fd_funk_rec_t             * rec;
      23             : 
      24             :   fd_account_meta_t const   * orig_meta;
      25             :   uchar             const   * orig_data;
      26             :   fd_funk_rec_t     const   * orig_rec;
      27             : 
      28             :   ulong                       starting_dlen;
      29             :   ulong                       starting_lamports;
      30             : 
      31             :   ulong starting_owner_dlen;
      32             : 
      33             :   /* Provide read/write mutual exclusion semantics.
      34             :      Used for single-threaded logic only, thus not comparable to a
      35             :      data synchronization lock. */
      36             : 
      37             :   ushort refcnt_excl;
      38             :   ushort refcnt_shared;
      39             : 
      40             :   uchar account_found;
      41             : };
      42             : typedef struct fd_borrowed_account fd_borrowed_account_t;
      43     6573885 : #define FD_BORROWED_ACCOUNT_FOOTPRINT (sizeof(fd_borrowed_account_t))
      44             : #define FD_BORROWED_ACCOUNT_ALIGN     (8UL)
      45     6573885 : #define FD_BORROWED_ACCOUNT_MAGIC     (0xF15EDF1C51F51AA1UL)
      46             : 
      47     5880906 : #define FD_BORROWED_ACCOUNT_DECL(_x)  fd_borrowed_account_t _x[1]; fd_borrowed_account_init(_x);
      48             : 
      49             : /* This macro provides the same scoping guarantees as the Agave client's
      50             :    borrowed account semantics. It allows for implict/explicit dropping of
      51             :    borrowed accounts' write locks. It's usage mirrors the use of
      52             :    FD_SCRATCH_SCOPE_{BEGIN,END}. It is also safe to use the original
      53             :    acquire/release api within the scoped macro in case you don't want
      54             :    variables to go out of scope. An example of this is in the extend
      55             :    instruction within the bpf loader.
      56             :    Equivalent to Agave's instruction_context::try_borrow_instruction_account()
      57             :    https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L647 */
      58             : 
      59       40638 : #define FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( _ctx, _idx, _account ) do {   \
      60       40638 :   if( FD_UNLIKELY( _idx>=(_ctx)->instr->acct_cnt ) ) {                    \
      61           9 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                     \
      62           9 :   }                                                                       \
      63       40638 :   fd_borrowed_account_t * _account = NULL;                                \
      64       40629 :   int _err = fd_instr_borrowed_account_view_idx( _ctx, _idx, &_account ); \
      65       40629 :   if( FD_UNLIKELY( _err != FD_ACC_MGR_SUCCESS ) ) {                       \
      66           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                     \
      67           0 :   }                                                                       \
      68       40629 :   int _acquire_result = fd_borrowed_account_acquire_write(_account);      \
      69       40629 :   if( FD_UNLIKELY( !_acquire_result ) ) {                                 \
      70         237 :     return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;                       \
      71         237 :   }                                                                       \
      72       40629 :   fd_borrowed_account_t *  __fd_borrowed_lock_guard_ ## __LINE__          \
      73       40392 :     __attribute__((cleanup(fd_borrowed_account_release_write_private)))   \
      74       40392 :     __attribute__((unused)) = _account;                                   \
      75       40392 :   do
      76       40392 : #define FD_BORROWED_ACCOUNT_DROP( _account_check ) while(0); (void)_account_check; } while(0)
      77             : 
      78             : FD_PROTOTYPES_BEGIN
      79             : 
      80             : fd_borrowed_account_t *
      81             : fd_borrowed_account_init( void * ptr );
      82             : 
      83             : void
      84             : fd_borrowed_account_resize( fd_borrowed_account_t * borrowed_account,
      85             :                             ulong                   dlen );
      86             : 
      87             : FD_FN_PURE static inline ulong
      88           0 : fd_borrowed_account_raw_size( fd_borrowed_account_t const * borrowed_account ) {
      89           0 :   ulong dlen = ( borrowed_account->const_meta != NULL ) ? borrowed_account->const_meta->dlen : 0;
      90           0 :   return sizeof(fd_account_meta_t) + dlen;
      91           0 : }
      92             : 
      93             : fd_borrowed_account_t *
      94             : fd_borrowed_account_make_modifiable( fd_borrowed_account_t * borrowed_account,
      95             :                                      void *                  buf );
      96             : 
      97             : /* In Agave, dummy accounts are sometimes created that contain metadata
      98             :    that differs from what's in the accounts DB.  For example, see
      99             :    handling of the executable bit in
     100             :    fd_executor_load_transaction_accounts().
     101             :    This allows us to emulate that by modifying metadata of read-only
     102             :    borrowed accounts without those modification writing through to
     103             :    funk.
     104             :  */
     105             : fd_borrowed_account_t *
     106             : fd_borrowed_account_make_readonly_copy( fd_borrowed_account_t * borrowed_account,
     107             :                                         void *                  buf );
     108             : 
     109             : void *
     110             : fd_borrowed_account_restore( fd_borrowed_account_t * borrowed_account );
     111             : 
     112             : void *
     113             : fd_borrowed_account_destroy( fd_borrowed_account_t * borrowed_account );
     114             : 
     115             : /* fd_borrowed_account_acquire_{read,write}_is_safe returns 1 if
     116             :    fd_borrowed_account_acquire_{read,write} will be successful for the
     117             :    given borrowed account.  If a lock is already held, returns 0. */
     118             : 
     119             : FD_FN_PURE static inline int
     120       94281 : fd_borrowed_account_acquire_write_is_safe( fd_borrowed_account_t const * rw ) {
     121       94281 :   return (!rw->refcnt_excl) & (!rw->refcnt_shared);
     122       94281 : }
     123             : 
     124             : FD_FN_PURE static inline int
     125           0 : fd_borrowed_account_acquire_read_is_safe( fd_borrowed_account_t const * rw ) {
     126           0 :   return (!rw->refcnt_excl);
     127           0 : }
     128             : 
     129             : /* fd_borrowed_account_acquire_write acquires write/exclusive access.
     130             :    Causes all other write or read acquire attempts will fail.  Returns 1
     131             :    on success, 0 on failure. */
     132             : 
     133             : static inline int
     134       53889 : fd_borrowed_account_acquire_write( fd_borrowed_account_t * rw ) {
     135       53889 :   if( FD_UNLIKELY( !fd_borrowed_account_acquire_write_is_safe( rw ) ) ) {
     136         237 :     return 0;
     137         237 :   }
     138       53652 :   rw->refcnt_excl = (ushort)1;
     139       53652 :   return 1;
     140       53889 : }
     141             : 
     142             : /* fd_borrowed_account_release_write{_private} releases a write/exclusive
     143             :    access handle. The private version should only be used by the try borrow
     144             :    scoping macro. */
     145             : 
     146             : static inline void
     147       51114 : fd_borrowed_account_release_write( fd_borrowed_account_t * rw ) {
     148       51114 :   FD_TEST( rw->refcnt_excl==1U );
     149       51114 :   rw->refcnt_excl = (ushort)0;
     150       51114 : }
     151             : 
     152             : static inline void
     153       40392 : fd_borrowed_account_release_write_private(fd_borrowed_account_t ** rw ) {
     154             :   /* Only release if it is not yet released */
     155       40392 :   if( !fd_borrowed_account_acquire_write_is_safe( *rw ) ) {
     156       40332 :     fd_borrowed_account_release_write( *rw );
     157       40332 :   }
     158       40392 :   rw = NULL;
     159       40392 : }
     160             : 
     161             : /* fd_borrowed_account_acquire_read acquires read/shared access.  Causes
     162             :    write attempts to fail.  Further attempts to read will succeed. */
     163             : 
     164             : static inline int
     165           0 : fd_borrowed_account_acquire_read( fd_borrowed_account_t * rw ) {
     166           0 :   if( FD_UNLIKELY( !fd_borrowed_account_acquire_read_is_safe( rw ) ) )
     167           0 :     return 0;
     168           0 :   rw->refcnt_shared = (ushort)( rw->refcnt_shared + 1U );
     169           0 :   return 1;
     170           0 : }
     171             : 
     172             : /* fd_borrowed_account_release_read releases a read/shared access
     173             :    handle. */
     174             : 
     175             : static inline void
     176           0 : fd_borrowed_account_release_read( fd_borrowed_account_t * rw ) {
     177           0 :   FD_TEST( rw->refcnt_shared>0U );
     178           0 :   rw->refcnt_shared--;
     179           0 : }
     180             : 
     181             : FD_PROTOTYPES_END
     182             : 
     183             : #endif /* HEADER_fd_src_flamenco_runtime_fd_borrowed_account_h */

Generated by: LCOV version 1.14