From d87cbed7ebf172aa9cf68e9eeada75b549776ab2 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sun, 30 Aug 2026 16:34:18 +0200 Subject: [PATCH] Probe system-wide tracepoints and RAPL. --- monitor/src/monitor.cpp | 93 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/monitor/src/monitor.cpp b/monitor/src/monitor.cpp index 3e6a8414..91ab07df 100644 --- a/monitor/src/monitor.cpp +++ b/monitor/src/monitor.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -73,6 +74,98 @@ static bool ProcessIsAlive( pid_t pid ) return state && state[1] == ' ' && state[2] != 'Z' && state[2] != '\0'; } +static const char* GetTraceFsPath() +{ + static char path[ 4096 ]; + static char debugPath[ 4096 ]; + bool haveDebug = false; + FILE* f = fopen( "/proc/mounts", "r" ); + if( !f ) return nullptr; + char line[ 4096 ]; + while( fgets( line, sizeof( line ), f ) ) + { + char dir[ 4096 ]; + char type[ 64 ]; + if( sscanf( line, "%*s %4095s %63s", dir, type ) != 2 ) continue; + if( strcmp( type, "tracefs" ) == 0 ) + { + snprintf( path, sizeof( path ), "%s", dir ); + fclose( f ); + return path; + } + if( !haveDebug && strcmp( type, "debugfs" ) == 0 ) + { + snprintf( debugPath, sizeof( debugPath ), "%s/tracing", dir ); + haveDebug = true; + } + } + fclose( f ); + if( haveDebug ) + { + snprintf( path, sizeof( path ), "%s", debugPath ); + return path; + } + return nullptr; +} + +enum class TracepointStatus { Open, NoTraceFs, IdNotReadable, OpenDenied }; + +// open a system-wide per-CPU tracepoint (the client's sched/vblank shape); +// report the failure distinctly - tracefs readability (root) and the perf open (paranoid/CAP_PERFMON) are independent gates. +static TracepointStatus CheckSystemWideTracepoint( const char* eventPath ) +{ + const char* traceFs = GetTraceFsPath(); + if( !traceFs ) return TracepointStatus::NoTraceFs; + + char path[512]; + snprintf( path, sizeof( path ), "%s%s/id", traceFs, eventPath ); + FILE* f = fopen( path, "r" ); + if( !f ) return TracepointStatus::IdNotReadable; + int id = -1; + if( fscanf( f, "%d", &id ) != 1 ) id = -1; + fclose( f ); + if( id < 0 ) return TracepointStatus::IdNotReadable; + + perf_event_attr pe = {}; + pe.type = PERF_TYPE_TRACEPOINT; + pe.size = sizeof( pe ); + pe.config = (uint64_t)id; + pe.sample_period = 1; + pe.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_RAW; + pe.disabled = 1; + pe.inherit = 1; + + const long fd = syscall( __NR_perf_event_open, &pe, -1, 0, -1, 0 ); + if( fd < 0 ) return TracepointStatus::OpenDenied; + close( (int)fd ); + return TracepointStatus::Open; +} + +// Power plots read RAPL energy counters (the client scans the same tree). +static bool CanReadRapl() +{ + const char* base = "/sys/devices/virtual/powercap/intel-rapl"; + DIR* dir = opendir( base ); + if( !dir ) return false; + struct dirent* ent; + bool ok = false; + while( ( ent = readdir( dir ) ) ) + { + if( ent->d_type != DT_DIR || strncmp( ent->d_name, "intel-rapl:", 11 ) != 0 ) continue; + char path[512]; + snprintf( path, sizeof( path ), "%s/%s/energy_uj", base, ent->d_name ); + FILE* f = fopen( path, "r" ); + if( f ) + { + fclose( f ); + ok = true; + break; + } + } + closedir( dir ); + return ok; +} + // Try opening one perf event against the target so we fail fast with a clear // message instead of starting the profiler and silently producing no samples. static bool PreflightPerfEventOpen( pid_t pid )