LCOV - code coverage report
Current view: top level - disco/diag - fd_diag_tile.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 287 0.0 %
Date: 2026-01-24 04:58:51 Functions: 0 10 0.0 %

          Line data    Source code
       1             : #include "../metrics/fd_metrics.h"
       2             : #include "../stem/fd_stem.h"
       3             : #include "../topo/fd_topo.h"
       4             : 
       5             : #include <fcntl.h>
       6             : #include <errno.h>
       7             : #include <stdlib.h>
       8             : #include <sys/types.h> /* SEEK_SET */
       9             : #include <time.h>
      10             : #include <unistd.h>
      11             : 
      12             : #include "generated/fd_diag_tile_seccomp.h"
      13             : 
      14           0 : #define REPORT_INTERVAL_MILLIS (100L)
      15             : 
      16             : struct fd_diag_tile {
      17             :   long next_report_nanos;
      18             : 
      19             :   ulong tile_cnt;
      20             : 
      21             :   ulong starttime_nanos[ FD_TILE_MAX ];
      22             :   long  first_seen_died[ FD_TILE_MAX ];
      23             : 
      24             :   int stat_fds[ FD_TILE_MAX ];
      25             :   int sched_fds[ FD_TILE_MAX ];
      26             : 
      27             :   volatile ulong * metrics[ FD_TILE_MAX ];
      28             : };
      29             : 
      30             : typedef struct fd_diag_tile fd_diag_tile_t;
      31             : 
      32             : FD_FN_CONST static inline ulong
      33           0 : scratch_align( void ) {
      34           0 :   return 128UL;
      35           0 : }
      36             : 
      37             : FD_FN_PURE static inline ulong
      38           0 : scratch_footprint( fd_topo_tile_t const * tile ) {
      39           0 :   (void)tile;
      40           0 :   ulong l = FD_LAYOUT_INIT;
      41           0 :   l = FD_LAYOUT_APPEND( l, alignof( fd_diag_tile_t ), sizeof( fd_diag_tile_t ) );
      42           0 :   return FD_LAYOUT_FINI( l, scratch_align() );
      43           0 : }
      44             : 
      45             : static int
      46             : read_stat_file( int              fd,
      47             :                 ulong            ns_per_tick,
      48           0 :                 volatile ulong * metrics ) {
      49           0 :   if( FD_UNLIKELY( -1==lseek( fd, 0, SEEK_SET ) ) ) FD_LOG_ERR(( "lseek failed (%i-%s)", errno, strerror( errno ) ));
      50             : 
      51           0 :   char contents[ 4096 ] = {0};
      52           0 :   ulong contents_len = 0UL;
      53             : 
      54           0 :   while( 1 ) {
      55           0 :     if( FD_UNLIKELY( contents_len>=sizeof( contents ) ) ) FD_LOG_ERR(( "stat contents overflow" ));
      56           0 :     long n = read( fd, contents + contents_len, sizeof( contents ) - contents_len );
      57           0 :     if( FD_UNLIKELY( -1==n ) ) {
      58           0 :       if( FD_UNLIKELY( errno==ESRCH ) ) return 1;
      59           0 :       FD_LOG_ERR(( "read failed (%i-%s)", errno, strerror( errno ) ));
      60           0 :     }
      61           0 :     if( FD_LIKELY( 0==n ) ) break;
      62           0 :     contents_len += (ulong)n;
      63           0 :   }
      64             : 
      65             :   /* Parse stat file: fields are space-separated.
      66             :      Field 10 (1-indexed) = minflt, field 12 = majflt,
      67             :      field 14 = utime, field 15 = stime (all in clock ticks). */
      68           0 :   char * saveptr;
      69           0 :   char * token = strtok_r( contents, " ", &saveptr );
      70           0 :   ulong field_idx = 0UL;
      71             : 
      72           0 :   while( token ) {
      73           0 :     if( FD_UNLIKELY( 9UL==field_idx ) ) {
      74           0 :       char * endptr;
      75           0 :       ulong minflt = strtoul( token, &endptr, 10 );
      76           0 :       if( FD_UNLIKELY( *endptr!='\0' || minflt==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul failed for minflt" ));
      77           0 :       metrics[ FD_METRICS_COUNTER_TILE_PAGE_FAULT_MINOR_COUNT_OFF ] = minflt;
      78           0 :     } else if( FD_UNLIKELY( 11UL==field_idx ) ) {
      79           0 :       char * endptr;
      80           0 :       ulong majflt = strtoul( token, &endptr, 10 );
      81           0 :       if( FD_UNLIKELY( *endptr!='\0' || majflt==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul failed for majflt" ));
      82           0 :       metrics[ FD_METRICS_COUNTER_TILE_PAGE_FAULT_MAJOR_COUNT_OFF ] = majflt;
      83           0 :     } else if( FD_UNLIKELY( 13UL==field_idx ) ) {
      84           0 :       char * endptr;
      85           0 :       ulong utime_ticks = strtoul( token, &endptr, 10 );
      86           0 :       if( FD_UNLIKELY( *endptr!='\0' || utime_ticks==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul failed for utime" ));
      87           0 :       metrics[ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_USER_OFF ] = utime_ticks*ns_per_tick;
      88           0 :     } else if( FD_UNLIKELY( 14UL==field_idx ) ) {
      89           0 :       char * endptr;
      90           0 :       ulong stime_ticks = strtoul( token, &endptr, 10 );
      91           0 :       if( FD_UNLIKELY( *endptr!='\0' || stime_ticks==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul failed for stime" ));
      92           0 :       metrics[ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_SYSTEM_OFF ] = stime_ticks*ns_per_tick;
      93           0 :       break; /* No need to parse stat further */
      94           0 :     }
      95           0 :     token = strtok_r( NULL, " ", &saveptr );
      96           0 :     field_idx++;
      97           0 :   }
      98             : 
      99           0 :   if( FD_UNLIKELY( field_idx!=14UL ) ) FD_LOG_ERR(( "stime (field 15) not found in stat" ));
     100             : 
     101           0 :   return 0;
     102           0 : }
     103             : 
     104             : static int
     105             : read_sched_file( int              fd,
     106           0 :                  volatile ulong * metrics ) {
     107           0 :   if( FD_UNLIKELY( -1==lseek( fd, 0, SEEK_SET ) ) ) FD_LOG_ERR(( "lseek failed (%i-%s)", errno, strerror( errno ) ));
     108             : 
     109           0 :   char contents[ 4096 ] = {0};
     110           0 :   ulong contents_len = 0UL;
     111             : 
     112           0 :   while( 1 ) {
     113           0 :     if( FD_UNLIKELY( contents_len>=sizeof( contents ) ) ) FD_LOG_ERR(( "sched contents overflow" ));
     114           0 :     long n = read( fd, contents + contents_len, sizeof( contents ) - contents_len );
     115           0 :     if( FD_UNLIKELY( -1==n ) ) {
     116           0 :       if( FD_UNLIKELY( errno==ESRCH ) ) return 1;
     117           0 :       FD_LOG_ERR(( "read failed (%i-%s)", errno, strerror( errno ) ));
     118           0 :     }
     119           0 :     if( FD_LIKELY( 0==n ) ) break;
     120           0 :     contents_len += (ulong)n;
     121           0 :   }
     122             : 
     123           0 :   int found_wait_sum = 0;
     124           0 :   int found_voluntary = 0;
     125           0 :   int found_involuntary = 0;
     126             : 
     127           0 :   char * line = contents;
     128           0 :   while( 1 ) {
     129           0 :     char * next_line = strchr( line, '\n' );
     130           0 :     if( FD_UNLIKELY( NULL==next_line ) ) break;
     131           0 :     *next_line = '\0';
     132             : 
     133           0 :     if( FD_UNLIKELY( !strncmp( line, "wait_sum", 8UL ) ) ) {
     134           0 :       char * colon = strchr( line, ':' );
     135           0 :       if( FD_LIKELY( colon ) ) {
     136           0 :         char * value = colon + 1;
     137           0 :         while( ' '==*value || '\t'==*value ) value++;
     138             :         /* wait_sum is displayed as seconds.microseconds (e.g., "123.456789").
     139             :            Parse both components as integers and convert to nanoseconds. */
     140           0 :         char * endptr;
     141           0 :         ulong seconds = strtoul( value, &endptr, 10 );
     142           0 :         if( FD_UNLIKELY( '.'!=*endptr ) ) FD_LOG_ERR(( "expected '.' after seconds in wait_sum" ));
     143           0 :         if( FD_UNLIKELY( seconds==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul overflow for wait_sum seconds" ));
     144           0 :         ulong microseconds = strtoul( endptr + 1, &endptr, 10 );
     145           0 :         if( FD_UNLIKELY( '\0'!=*endptr ) ) FD_LOG_ERR(( "unexpected char after microseconds in wait_sum" ));
     146           0 :         if( FD_UNLIKELY( microseconds==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul overflow for wait_sum microseconds" ));
     147           0 :         ulong wait_sum_ns = seconds*1000000000UL + microseconds*1000UL;
     148           0 :         metrics[ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_WAIT_OFF ] = wait_sum_ns;
     149           0 :         found_wait_sum = 1;
     150           0 :       }
     151           0 :     } else if( FD_UNLIKELY( !strncmp( line, "nr_voluntary_switches", 21UL ) ) ) {
     152           0 :       char * colon = strchr( line, ':' );
     153           0 :       if( FD_LIKELY( colon ) ) {
     154           0 :         char * value = colon + 1;
     155           0 :         while( ' '==*value || '\t'==*value ) value++;
     156           0 :         char * endptr;
     157           0 :         ulong voluntary_switches = strtoul( value, &endptr, 10 );
     158           0 :         if( FD_UNLIKELY( '\0'!=*endptr ) ) FD_LOG_ERR(( "unexpected char after nr_voluntary_switches" ));
     159           0 :         if( FD_UNLIKELY( voluntary_switches==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul overflow for nr_voluntary_switches" ));
     160           0 :         metrics[ FD_METRICS_COUNTER_TILE_CONTEXT_SWITCH_VOLUNTARY_COUNT_OFF ] = voluntary_switches;
     161           0 :         found_voluntary = 1;
     162           0 :       }
     163           0 :     } else if( FD_UNLIKELY( !strncmp( line, "nr_involuntary_switches", 23UL ) ) ) {
     164           0 :       char * colon = strchr( line, ':' );
     165           0 :       if( FD_LIKELY( colon ) ) {
     166           0 :         char * value = colon + 1;
     167           0 :         while( ' '==*value || '\t'==*value ) value++;
     168           0 :         char * endptr;
     169           0 :         ulong involuntary_switches = strtoul( value, &endptr, 10 );
     170           0 :         if( FD_UNLIKELY( '\0'!=*endptr ) ) FD_LOG_ERR(( "unexpected char after nr_involuntary_switches" ));
     171           0 :         if( FD_UNLIKELY( involuntary_switches==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul overflow for nr_involuntary_switches" ));
     172           0 :         metrics[ FD_METRICS_COUNTER_TILE_CONTEXT_SWITCH_INVOLUNTARY_COUNT_OFF ] = involuntary_switches;
     173           0 :         found_involuntary = 1;
     174           0 :       }
     175           0 :     }
     176             : 
     177           0 :     line = next_line + 1;
     178           0 :   }
     179             : 
     180             :   // wait_sum not present on kernels compiled without CONFIG_SCHEDSTATS=y
     181             :   // if( FD_UNLIKELY( !found_wait_sum ) ) FD_LOG_ERR(( "wait_sum not found in sched file" ));
     182           0 :   (void)found_wait_sum;
     183           0 :   if( FD_UNLIKELY( !found_voluntary ) ) FD_LOG_ERR(( "nr_voluntary_switches not found in sched file" ));
     184           0 :   if( FD_UNLIKELY( !found_involuntary ) ) FD_LOG_ERR(( "nr_involuntary_switches not found in sched file" ));
     185             : 
     186           0 :   return 0;
     187           0 : }
     188             : 
     189             : static void
     190             : before_credit( fd_diag_tile_t *    ctx,
     191             :                fd_stem_context_t * stem,
     192           0 :                int *               charge_busy ) {
     193           0 :   (void)stem;
     194             : 
     195           0 :   long now = fd_log_wallclock();
     196           0 :   if( now<ctx->next_report_nanos ) {
     197           0 :     long diff = ctx->next_report_nanos - now;
     198           0 :     diff = fd_long_min( diff, 2e6 /* 2ms */ );
     199           0 :     struct timespec const ts = {
     200           0 :       .tv_sec  = diff / (long)1e9,
     201           0 :       .tv_nsec = diff % (long)1e9
     202           0 :     };
     203           0 :     clock_nanosleep( CLOCK_REALTIME, 0, &ts, NULL );
     204           0 :     return;
     205           0 :   }
     206           0 :   ctx->next_report_nanos += REPORT_INTERVAL_MILLIS*1000L*1000L;
     207             : 
     208           0 :   *charge_busy = 1;
     209             : 
     210           0 :   struct timespec boottime;
     211           0 :   if( FD_UNLIKELY( -1==clock_gettime( CLOCK_BOOTTIME, &boottime ) ) ) FD_LOG_ERR(( "clock_gettime(CLOCK_BOOTTIME) failed (%i-%s)", errno, strerror( errno ) ));
     212           0 :   ulong now_since_boot_nanos = (ulong)boottime.tv_sec*1000000000UL + (ulong)boottime.tv_nsec;
     213             : 
     214           0 :   for( ulong i=0UL; i<ctx->tile_cnt; i++ ) {
     215           0 :     if( FD_UNLIKELY( -1==ctx->stat_fds[ i ] ) ) continue;
     216             : 
     217             :     /* CLK_TCK is typically 100, so 1 tick = 10ms = 10,000,000 ns */
     218           0 :     int process_died1 = read_stat_file( ctx->stat_fds[ i ], 10000000UL, ctx->metrics[ i ] );
     219           0 :     int process_died2 = read_sched_file( ctx->sched_fds[ i ], ctx->metrics[ i ] );
     220             : 
     221           0 :     if( FD_UNLIKELY( process_died1 || process_died2 ) ) {
     222           0 :       ctx->stat_fds[ i ] = -1;
     223           0 :       continue;
     224           0 :     }
     225             : 
     226           0 :     ulong task_lifetime_nanos = now_since_boot_nanos - ctx->starttime_nanos[ i ];
     227           0 :     ulong user_nanos   = ctx->metrics[ i ][ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_USER_OFF ];
     228           0 :     ulong system_nanos = ctx->metrics[ i ][ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_SYSTEM_OFF ];
     229           0 :     ulong wait_nanos   = ctx->metrics[ i ][ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_WAIT_OFF ];
     230           0 :     ulong busy_nanos   = user_nanos+system_nanos+wait_nanos;
     231           0 :     ulong idle_nanos   = (task_lifetime_nanos>busy_nanos) ? (task_lifetime_nanos-busy_nanos) : 0UL;
     232             : 
     233             :     /* Counter can't go backwards in Prometheus else it thinks the
     234             :        application restarted.  Use max to ensure monotonicity. */
     235           0 :     ctx->metrics[ i ][ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_IDLE_OFF ] = fd_ulong_max( idle_nanos, ctx->metrics[ i ][ FD_METRICS_COUNTER_TILE_CPU_DURATION_NANOS_IDLE_OFF ] );
     236           0 :   }
     237             : 
     238           0 :   for( ulong i=0UL; i<ctx->tile_cnt; i++ ) {
     239           0 :     if( FD_LIKELY( -1!=ctx->stat_fds[ i ] ) ) continue;
     240             : 
     241             :     /* The tile died, but it's a tile which is allowed to shutdown, so
     242             :        just stop updating metrics for it. */
     243           0 :     if( FD_LIKELY( 2UL==ctx->metrics[ i ][ FD_METRICS_GAUGE_TILE_STATUS_OFF ] ) ) continue;
     244             : 
     245             :     /* Supervisor is going to bring the whole process tree down if any
     246             :        of the target PIDs died, so we can ignore this and wait. */
     247           0 :     if( FD_UNLIKELY( !ctx->first_seen_died[ i ] ) ) {
     248           0 :       ctx->first_seen_died[ i ] = now;
     249           0 :     } else if( FD_LIKELY( ctx->first_seen_died[ i ]==LONG_MAX ) ) {
     250             :       /* We already reported this, so we can ignore it. */
     251           0 :     } else if( FD_UNLIKELY( now-ctx->first_seen_died[ i ] < 10L*1000L*1000L*1000L ) ) {
     252             :       /* Wait 10 seconds for supervisor to kill us before reporting WARNING */
     253           0 :     } else {
     254           0 :       FD_LOG_WARNING(( "cannot get metrics for dead tile idx %lu", i ));
     255           0 :       ctx->first_seen_died[ i ] = LONG_MAX;
     256           0 :     }
     257           0 :   }
     258           0 : }
     259             : 
     260             : static void
     261             : privileged_init( fd_topo_t *      topo,
     262           0 :                  fd_topo_tile_t * tile ) {
     263           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     264             : 
     265           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     266           0 :   fd_diag_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_diag_tile_t), sizeof(fd_diag_tile_t) );
     267             : 
     268           0 :   FD_TEST( topo->tile_cnt<FD_TILE_MAX );
     269             : 
     270           0 :   FD_TEST( 100L == sysconf( _SC_CLK_TCK ) );
     271             : 
     272           0 :   ctx->tile_cnt = topo->tile_cnt;
     273           0 :   for( ulong i=0UL; i<FD_TILE_MAX; i++ ) {
     274           0 :     ctx->stat_fds[ i ]  = -1;
     275           0 :     ctx->sched_fds[ i ] = -1;
     276           0 :   }
     277             : 
     278           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     279           0 :     ulong * metrics = fd_metrics_join( fd_topo_obj_laddr( topo, topo->tiles[ i ].metrics_obj_id ) );
     280             : 
     281           0 :     for(;;) {
     282           0 :       ulong pid, tid;
     283           0 :       if( FD_UNLIKELY( tile->id==i ) ) {
     284           0 :         pid = fd_sandbox_getpid();
     285           0 :         tid = fd_sandbox_gettid();
     286           0 :       } else {
     287           0 :         pid = fd_metrics_tile( metrics )[ FD_METRICS_GAUGE_TILE_PID_OFF ];
     288           0 :         tid = fd_metrics_tile( metrics )[ FD_METRICS_GAUGE_TILE_TID_OFF ];
     289           0 :         if( FD_UNLIKELY( !pid || !tid ) ) {
     290           0 :           FD_SPIN_PAUSE();
     291           0 :           continue;
     292           0 :         }
     293           0 :       }
     294             : 
     295           0 :       ctx->metrics[ i ] = fd_metrics_tile( metrics );
     296             : 
     297           0 :       char path[ 64UL ];
     298           0 :       FD_TEST( fd_cstr_printf_check( path, sizeof( path ), NULL, "/proc/%lu/task/%lu/stat", pid, tid ) );
     299           0 :       ctx->stat_fds[ i ] = open( path, O_RDONLY );
     300           0 :       if( FD_UNLIKELY( -1==ctx->stat_fds[ i ] ) ) {
     301             :         /* Might be a tile that's allowed to shutdown already did so
     302             :            before we got to here, due to a race condition.  Just
     303             :            proceed, we will not be able to get metrics for the shut
     304             :            down process. */
     305           0 :         if( FD_LIKELY( 2UL!=ctx->metrics[ i ][ FD_METRICS_GAUGE_TILE_STATUS_OFF ] ) ) FD_LOG_ERR(( "open stat failed (%i-%s)", errno, strerror( errno ) ));
     306           0 :         break;
     307           0 :       }
     308             : 
     309           0 :       FD_TEST( fd_cstr_printf_check( path, sizeof( path ), NULL, "/proc/%lu/task/%lu/sched", pid, tid ) );
     310           0 :       ctx->sched_fds[ i ] = open( path, O_RDONLY );
     311           0 :       if( FD_UNLIKELY( -1==ctx->sched_fds[ i ] ) ) {
     312           0 :         if( FD_LIKELY( 2UL!=ctx->metrics[ i ][ FD_METRICS_GAUGE_TILE_STATUS_OFF ] ) ) FD_LOG_ERR(( "open sched failed (%i-%s)", errno, strerror( errno ) ));
     313           0 :         ctx->stat_fds[ i ] = -1;
     314           0 :       }
     315           0 :       break;
     316           0 :     }
     317           0 :   }
     318           0 : }
     319             : 
     320             : /* Read starttime (field 22) from stat file. Returns 0 on success, 1 if
     321             :    process died (ESRCH). */
     322             : 
     323             : static int
     324             : read_starttime( int     fd,
     325             :                 ulong   ns_per_tick,
     326           0 :                 ulong * out_starttime_nanos ) {
     327           0 :   char contents[ 4096 ] = {0};
     328           0 :   ulong contents_len = 0UL;
     329             : 
     330           0 :   while( 1 ) {
     331           0 :     if( FD_UNLIKELY( contents_len>=sizeof( contents ) ) ) FD_LOG_ERR(( "stat contents overflow" ));
     332           0 :     long n = read( fd, contents + contents_len, sizeof( contents ) - contents_len );
     333           0 :     if( FD_UNLIKELY( -1==n ) ) {
     334           0 :       if( FD_UNLIKELY( errno==ESRCH ) ) return 1;
     335           0 :       FD_LOG_ERR(( "read stat failed (%i-%s)", errno, strerror( errno ) ));
     336           0 :     }
     337           0 :     if( FD_LIKELY( 0L==n ) ) break;
     338           0 :     contents_len += (ulong)n;
     339           0 :   }
     340             : 
     341             :   /* Parse field 22 (starttime) from stat file */
     342           0 :   char * saveptr;
     343           0 :   char * token = strtok_r( contents, " ", &saveptr );
     344           0 :   ulong field_idx = 0UL;
     345             : 
     346           0 :   while( token && field_idx<21UL ) {
     347           0 :     token = strtok_r( NULL, " ", &saveptr );
     348           0 :     field_idx++;
     349           0 :   }
     350             : 
     351           0 :   if( FD_UNLIKELY( !token || field_idx!=21UL ) ) FD_LOG_ERR(( "starttime (field 22) not found in stat" ));
     352             : 
     353           0 :   char * endptr;
     354           0 :   ulong starttime_ticks = strtoul( token, &endptr, 10 );
     355           0 :   if( FD_UNLIKELY( *endptr!=' ' && *endptr!='\0' ) ) FD_LOG_ERR(( "strtoul failed for starttime" ));
     356           0 :   if( FD_UNLIKELY( starttime_ticks==ULONG_MAX ) ) FD_LOG_ERR(( "strtoul overflow for starttime" ));
     357             : 
     358           0 :   *out_starttime_nanos = starttime_ticks * ns_per_tick;
     359           0 :   return 0;
     360           0 : }
     361             : 
     362             : static void
     363             : unprivileged_init( fd_topo_t *      topo,
     364           0 :                    fd_topo_tile_t * tile ) {
     365           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     366             : 
     367           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     368           0 :   fd_diag_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_diag_tile_t), sizeof(fd_diag_tile_t) );
     369             : 
     370           0 :   memset( ctx->first_seen_died, 0, sizeof( ctx->first_seen_died ) );
     371           0 :   ctx->next_report_nanos = fd_log_wallclock();
     372             : 
     373             :   /* Read starttime (field 22) once at init for idle time calculation.
     374             :      CLK_TCK is always 100, so 1 tick = 10ms = 10,000,000 ns. */
     375           0 :   for( ulong i=0UL; i<ctx->tile_cnt; i++ ) {
     376           0 :     if( FD_LIKELY( -1!=ctx->stat_fds[ i ] ) ) {
     377           0 :       int died = read_starttime( ctx->stat_fds[ i ], 10000000UL, &ctx->starttime_nanos[ i ] );
     378           0 :       if( FD_UNLIKELY( died ) ) ctx->stat_fds[ i ] = -1;
     379           0 :     }
     380           0 :   }
     381             : 
     382           0 :   ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, 1UL );
     383           0 :   if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
     384           0 :     FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
     385           0 : }
     386             : 
     387             : static ulong
     388             : populate_allowed_seccomp( fd_topo_t const *      topo,
     389             :                           fd_topo_tile_t const * tile,
     390             :                           ulong                  out_cnt,
     391           0 :                           struct sock_filter *   out ) {
     392           0 :   (void)topo;
     393           0 :   (void)tile;
     394             : 
     395           0 :   populate_sock_filter_policy_fd_diag_tile( out_cnt, out, (uint)fd_log_private_logfile_fd() );
     396           0 :   return sock_filter_policy_fd_diag_tile_instr_cnt;
     397           0 : }
     398             : 
     399             : static ulong
     400             : populate_allowed_fds( fd_topo_t const *      topo,
     401             :                       fd_topo_tile_t const * tile,
     402             :                       ulong                  out_fds_cnt,
     403           0 :                       int *                  out_fds ) {
     404           0 :   void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     405             : 
     406           0 :   FD_SCRATCH_ALLOC_INIT( l, scratch );
     407           0 :   fd_diag_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_diag_tile_t), sizeof(fd_diag_tile_t) );
     408             : 
     409           0 :   if( FD_UNLIKELY( out_fds_cnt<2UL+2UL*ctx->tile_cnt ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
     410             : 
     411           0 :   ulong out_cnt = 0UL;
     412           0 :   out_fds[ out_cnt++ ] = 2; /* stderr */
     413           0 :   if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
     414           0 :     out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
     415           0 :   for( ulong i=0UL; i<ctx->tile_cnt; i++ ) {
     416           0 :     if( -1!=ctx->stat_fds[ i ] )  out_fds[ out_cnt++ ] = ctx->stat_fds[ i ];  /* /proc/<pid>/task/<tid>/stat */
     417           0 :     if( -1!=ctx->sched_fds[ i ] ) out_fds[ out_cnt++ ] = ctx->sched_fds[ i ]; /* /proc/<pid>/task/<tid>/sched */
     418           0 :   }
     419           0 :   return out_cnt;
     420           0 : }
     421             : 
     422           0 : #define STEM_BURST (1UL)
     423           0 : #define STEM_LAZY  ((long)10e6) /* 10ms */
     424             : 
     425           0 : #define STEM_CALLBACK_CONTEXT_TYPE  fd_diag_tile_t
     426           0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_diag_tile_t)
     427             : 
     428           0 : #define STEM_CALLBACK_BEFORE_CREDIT before_credit
     429             : 
     430             : #include "../../disco/stem/fd_stem.c"
     431             : 
     432             : fd_topo_run_tile_t fd_tile_diag = {
     433             :   .name                     = "diag",
     434             :   .populate_allowed_seccomp = populate_allowed_seccomp,
     435             :   .populate_allowed_fds     = populate_allowed_fds,
     436             :   .scratch_align            = scratch_align,
     437             :   .scratch_footprint        = scratch_footprint,
     438             :   .privileged_init          = privileged_init,
     439             :   .unprivileged_init        = unprivileged_init,
     440             :   .run                      = stem_run,
     441             : };

Generated by: LCOV version 1.14