LCOV - code coverage report
Current view: top level - util/racesan - fd_racesan_async.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 55 0.0 %
Date: 2025-10-13 04:42:14 Functions: 0 8 0.0 %

          Line data    Source code
       1             : #include "fd_racesan_async.h"
       2             : #include "../../util/fd_util.h"
       3             : #include <errno.h>
       4             : 
       5             : /* fd_racesan_async_yield context switches out to the caller of the
       6             :    fd_racesan_async_step function. */
       7             : 
       8             : static void
       9           0 : fd_racesan_async_yield( fd_racesan_async_t * async ) {
      10           0 :   if( FD_UNLIKELY( 0!=swapcontext( &async->ctx, FD_VOLATILE_CONST( async->caller ) ) ) ) {
      11           0 :     FD_LOG_ERR(( "failed to yield from async fn: swapcontext failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      12           0 :   }
      13           0 : }
      14             : 
      15             : /* fd_racesan_async_hook is called whenever the target reaches a racesan
      16             :    hook.  The racesan_async logic here context-switches out back to the
      17             :    caller of step. */
      18             : 
      19             : static void
      20             : fd_racesan_async_hook( void * ctx,
      21           0 :                        ulong  name_hash ) {
      22           0 :   fd_racesan_async_t * async = ctx;
      23           0 :   async->name_hash = name_hash;
      24           0 :   fd_racesan_exit();
      25           0 :   fd_racesan_async_yield( async );
      26           0 : }
      27             : 
      28             : /* fd_racesan_async_target is a long-lived / async function with its own
      29             :    stack. */
      30             : 
      31             : static void
      32           0 : fd_racesan_async_target( fd_racesan_async_t * async ) {
      33           0 :   fd_racesan_t racesan[1];
      34           0 :   fd_racesan_new( racesan, async );
      35           0 :   fd_racesan_inject_default( racesan, fd_racesan_async_hook );
      36           0 :   fd_racesan_enter( racesan );
      37           0 :   async->fn( async->fn_ctx );
      38           0 :   fd_racesan_delete( racesan );
      39             : 
      40           0 :   async->done = 1;
      41           0 :   fd_racesan_async_yield( async );
      42           0 : }
      43             : 
      44             : fd_racesan_async_t *
      45             : fd_racesan_async_new( fd_racesan_async_t *    async,
      46             :                       fd_racesan_async_fn_t * async_fn,
      47           0 :                       void *                  ctx ) {
      48           0 :   memset( async, 0, sizeof(fd_racesan_async_t) );
      49             : 
      50           0 :   async->fn_ctx = ctx;
      51           0 :   async->fn     = async_fn;
      52             : 
      53           0 :   if( FD_UNLIKELY( 0!=getcontext( &async->ctx ) ) ) {
      54           0 :     FD_LOG_ERR(( "getcontext failed" ));
      55           0 :   }
      56           0 :   async->ctx.uc_stack.ss_sp   = async->stack;
      57           0 :   async->ctx.uc_stack.ss_size = sizeof(async->stack);
      58           0 :   makecontext( &async->ctx, (void (*)( void ))fd_racesan_async_target, 1, async );
      59             : 
      60           0 :   return async;
      61           0 : }
      62             : 
      63             : void *
      64           0 : fd_racesan_async_delete( fd_racesan_async_t * async ) {
      65           0 :   (void)async;
      66           0 :   return NULL;
      67           0 : }
      68             : 
      69             : int
      70           0 : fd_racesan_async_step( fd_racesan_async_t * async ) {
      71           0 :   if( FD_UNLIKELY( async->done ) ) return 0;
      72             : 
      73           0 :   ucontext_t caller;
      74           0 :   async->caller = &caller;
      75           0 :   if( FD_UNLIKELY( 0!=swapcontext( &caller, &async->ctx ) ) ) {
      76           0 :     FD_LOG_ERR(( "failed to step into async fn: swapcontext failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      77           0 :   }
      78             :   /* fd_racesan_async_yield jumps to here */
      79           0 :   return 1;
      80           0 : }
      81             : 
      82             : int
      83             : fd_racesan_async_hook_name_eq( fd_racesan_async_t * async,
      84           0 :                                char const *         hook_name ) {
      85           0 :   ulong len  = strlen( hook_name );
      86           0 :   ulong hash = fd_racesan_strhash( hook_name, len );
      87           0 :   return async->name_hash==hash;
      88           0 : }
      89             : 
      90             : void
      91           0 : fd_racesan_async_reset( fd_racesan_async_t * async ) {
      92           0 :   makecontext( &async->ctx, (void (*)( void ))fd_racesan_async_target, 1, async );
      93           0 :   async->done = 0;
      94           0 : }

Generated by: LCOV version 1.14