LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_borrowed_account.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 51 58 87.9 %
Date: 2024-11-13 11:58:15 Functions: 31 896 3.5 %

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

Generated by: LCOV version 1.14