diff --git a/src/amdgpu.cpp b/src/amdgpu.cpp index 388fb5e418..c9d785b859 100644 --- a/src/amdgpu.cpp +++ b/src/amdgpu.cpp @@ -6,12 +6,12 @@ #include "amdgpu.h" #include "gpu.h" #include "cpu.h" +#include "file_utils.h" #include "overlay.h" #include "hud_elements.h" #include "logging.h" #include "mesa/util/macros.h" - #define IS_VALID_METRIC(FIELD) (FIELD != 0xffff) void AMDGPU::get_instant_metrics(struct amdgpu_common_metrics *metrics) { FILE *f; @@ -373,24 +373,11 @@ void AMDGPU::metrics_polling_thread() { } void AMDGPU::get_sysfs_metrics() { - int64_t value = 0; - if (sysfs_nodes.busy) { - rewind(sysfs_nodes.busy); - fflush(sysfs_nodes.busy); - int value = 0; - if (fscanf(sysfs_nodes.busy, "%d", &value) != 1) - value = 0; - metrics.load = value; - } + if (sysfs_nodes.busy) + metrics.load = read_as(sysfs_nodes.busy).value_or(0); - if (sysfs_nodes.memory_clock) { - rewind(sysfs_nodes.memory_clock); - fflush(sysfs_nodes.memory_clock); - if (fscanf(sysfs_nodes.memory_clock, "%" PRId64, &value) != 1) - value = 0; - - metrics.MemClock = value / 1000000; - } + if (sysfs_nodes.memory_clock) + metrics.MemClock = read_as(sysfs_nodes.memory_clock).value_or(0) / 1000000; // TODO: on some gpus this will use the power1_input instead // this value is instantaneous and should be averaged over time @@ -402,14 +389,8 @@ void AMDGPU::get_sysfs_metrics() { metrics.powerUsage = 0; } else #endif - if (sysfs_nodes.power_usage) { - rewind(sysfs_nodes.power_usage); - fflush(sysfs_nodes.power_usage); - if (fscanf(sysfs_nodes.power_usage, "%" PRId64, &value) != 1) - value = 0; - - metrics.powerUsage = value / 1000000; - } + if (sysfs_nodes.power_usage) + metrics.powerUsage = read_as(sysfs_nodes.power_usage).value_or(0) / 1000000; #ifndef TEST_ONLY if (!get_params()->enabled[OVERLAY_PARAM_ENABLED_gpu_power_limit]) { @@ -418,92 +399,39 @@ void AMDGPU::get_sysfs_metrics() { metrics.powerLimit = 0; } else #endif - if (sysfs_nodes.power_limit) { - rewind(sysfs_nodes.power_limit); - fflush(sysfs_nodes.power_limit); - if (fscanf(sysfs_nodes.power_limit, "%" PRId64, &value) != 1) - value = 0; - - metrics.powerLimit = value / 1000000; - } + if (sysfs_nodes.power_limit) + metrics.powerLimit = read_as(sysfs_nodes.power_limit).value_or(0) / 1000000; if (sysfs_nodes.fan) { - rewind(sysfs_nodes.fan); - fflush(sysfs_nodes.fan); - if (fscanf(sysfs_nodes.fan, "%" PRId64, &value) != 1) - value = 0; - metrics.fan_speed = value; + metrics.fan_speed = read_as(sysfs_nodes.fan).value_or(0); metrics.fan_rpm = true; } - if (sysfs_nodes.vram_total) { - rewind(sysfs_nodes.vram_total); - fflush(sysfs_nodes.vram_total); - if (fscanf(sysfs_nodes.vram_total, "%" PRId64, &value) != 1) - value = 0; - metrics.memoryTotal = float(value) / (1024 * 1024 * 1024); - } + if (sysfs_nodes.vram_total) + metrics.memoryTotal = float(read_as(sysfs_nodes.vram_total).value_or(0)) / (1024 * 1024 * 1024); + + if (sysfs_nodes.vram_used) + metrics.sys_vram_used = float(read_as(sysfs_nodes.vram_used).value_or(0)) / (1024 * 1024 * 1024); - if (sysfs_nodes.vram_used) { - rewind(sysfs_nodes.vram_used); - fflush(sysfs_nodes.vram_used); - if (fscanf(sysfs_nodes.vram_used, "%" PRId64, &value) != 1) - value = 0; - metrics.sys_vram_used = float(value) / (1024 * 1024 * 1024); - } // On some GPUs SMU can sometimes return the wrong temperature. // As HWMON is way more visible than the SMU metrics, let's always trust it as it is the most likely to work - if (sysfs_nodes.core_clock) { - rewind(sysfs_nodes.core_clock); - fflush(sysfs_nodes.core_clock); - if (fscanf(sysfs_nodes.core_clock, "%" PRId64, &value) != 1) - value = 0; + if (sysfs_nodes.core_clock) + metrics.CoreClock = read_as(sysfs_nodes.core_clock).value_or(0) / 1000000; - metrics.CoreClock = value / 1000000; - } + if (sysfs_nodes.temp) + metrics.temp = read_as(sysfs_nodes.temp).value_or(0) / 1000; - if (sysfs_nodes.temp){ - rewind(sysfs_nodes.temp); - fflush(sysfs_nodes.temp); - int value = 0; - if (fscanf(sysfs_nodes.temp, "%d", &value) != 1) - value = 0; - metrics.temp = value / 1000; - } + if (sysfs_nodes.junction_temp) + metrics.junction_temp = read_as(sysfs_nodes.junction_temp).value_or(0) / 1000; - if (sysfs_nodes.junction_temp){ - rewind(sysfs_nodes.junction_temp); - fflush(sysfs_nodes.junction_temp); - int value = 0; - if (fscanf(sysfs_nodes.junction_temp, "%d", &value) != 1) - value = 0; - metrics.junction_temp = value / 1000; - } + if (sysfs_nodes.memory_temp) + metrics.memory_temp = read_as(sysfs_nodes.memory_temp).value_or(0) / 1000; - if (sysfs_nodes.memory_temp){ - rewind(sysfs_nodes.memory_temp); - fflush(sysfs_nodes.memory_temp); - int value = 0; - if (fscanf(sysfs_nodes.memory_temp, "%d", &value) != 1) - value = 0; - metrics.memory_temp = value / 1000; - } - - if (sysfs_nodes.gtt_used) { - rewind(sysfs_nodes.gtt_used); - fflush(sysfs_nodes.gtt_used); - if (fscanf(sysfs_nodes.gtt_used, "%" PRId64, &value) != 1) - value = 0; - metrics.gtt_used = float(value) / (1024 * 1024 * 1024); - } + if (sysfs_nodes.gtt_used) + metrics.gtt_used = float(read_as(sysfs_nodes.gtt_used).value_or(0)) / (1024 * 1024 * 1024); - if (sysfs_nodes.gpu_voltage_soc) { - rewind(sysfs_nodes.gpu_voltage_soc); - fflush(sysfs_nodes.gpu_voltage_soc); - if (fscanf(sysfs_nodes.gpu_voltage_soc, "%" PRId64, &value) != 1) - value = 0; - metrics.voltage = value; - } + if (sysfs_nodes.gpu_voltage_soc) + metrics.voltage = read_as(sysfs_nodes.gpu_voltage_soc).value_or(0); } AMDGPU::AMDGPU(std::string pci_dev, uint32_t device_id, uint32_t vendor_id) { diff --git a/src/cpu.cpp b/src/cpu.cpp index f46fabad1a..a34a043b43 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -284,12 +284,8 @@ bool CPUStats::ReadcpuTempFile(int& temp) { if (!m_cpuTempFile) return false; - rewind(m_cpuTempFile); - fflush(m_cpuTempFile); - bool ret = (fscanf(m_cpuTempFile, "%d", &temp) == 1); - temp = temp / 1000; - - return ret; + temp = read_as(m_cpuTempFile).value_or(0) / 1000; + return temp == 0; } bool CPUStats::UpdateCpuTemp() { @@ -314,44 +310,32 @@ static bool get_cpu_power_k10temp(CPUPowerData* cpuPowerData, float& power) { if(powerData_k10temp->corePowerFile || powerData_k10temp->socPowerFile) { - rewind(powerData_k10temp->corePowerFile); - rewind(powerData_k10temp->socPowerFile); - fflush(powerData_k10temp->corePowerFile); - fflush(powerData_k10temp->socPowerFile); - int corePower, socPower; - if (fscanf(powerData_k10temp->corePowerFile, "%d", &corePower) != 1) - goto voltagebased; - if (fscanf(powerData_k10temp->socPowerFile, "%d", &socPower) != 1) - goto voltagebased; - power = (corePower + socPower) / 1000000; - return true; + auto const corePower = read_as(powerData_k10temp->corePowerFile); + auto const socPower = read_as(powerData_k10temp->socPowerFile); + if (corePower and socPower) { + power = (corePower.value() + socPower.value()) / 1000000; + return true; + } } - voltagebased: + if (!powerData_k10temp->coreVoltageFile || !powerData_k10temp->coreCurrentFile || !powerData_k10temp->socVoltageFile || !powerData_k10temp->socCurrentFile) return false; - rewind(powerData_k10temp->coreVoltageFile); - rewind(powerData_k10temp->coreCurrentFile); - rewind(powerData_k10temp->socVoltageFile); - rewind(powerData_k10temp->socCurrentFile); - - fflush(powerData_k10temp->coreVoltageFile); - fflush(powerData_k10temp->coreCurrentFile); - fflush(powerData_k10temp->socVoltageFile); - fflush(powerData_k10temp->socCurrentFile); - - int coreVoltage, coreCurrent; - int socVoltage, socCurrent; - if (fscanf(powerData_k10temp->coreVoltageFile, "%d", &coreVoltage) != 1) + auto const coreVoltage = read_as(powerData_k10temp->coreVoltageFile); + if (not coreVoltage) return false; - if (fscanf(powerData_k10temp->coreCurrentFile, "%d", &coreCurrent) != 1) + auto const coreCurrent = read_as(powerData_k10temp->coreCurrentFile); + if (not coreCurrent) return false; - if (fscanf(powerData_k10temp->socVoltageFile, "%d", &socVoltage) != 1) + auto const socVoltage = read_as(powerData_k10temp->socVoltageFile); + if (not socVoltage) return false; - if (fscanf(powerData_k10temp->socCurrentFile, "%d", &socCurrent) != 1) + auto const socCurrent = read_as(powerData_k10temp->socCurrentFile); + if (not socCurrent) return false; - power = (coreVoltage * coreCurrent + socVoltage * socCurrent) / 1000000; + power = (coreVoltage.value() * coreCurrent.value() + + socVoltage.value() * socCurrent.value()) / 1000000; return true; } @@ -362,20 +346,14 @@ static bool get_cpu_power_zenpower(CPUPowerData* cpuPowerData, float& power) { if (!powerData_zenpower->corePowerFile || !powerData_zenpower->socPowerFile) return false; - rewind(powerData_zenpower->corePowerFile); - rewind(powerData_zenpower->socPowerFile); - - fflush(powerData_zenpower->corePowerFile); - fflush(powerData_zenpower->socPowerFile); - - int corePower, socPower; - - if (fscanf(powerData_zenpower->corePowerFile, "%d", &corePower) != 1) + auto const corePower = read_as(powerData_zenpower->corePowerFile); + if (not corePower) return false; - if (fscanf(powerData_zenpower->socPowerFile, "%d", &socPower) != 1) + auto const socPower = read_as(powerData_zenpower->socPowerFile); + if (not socPower) return false; - power = (corePower + socPower) / 1000000; + power = (corePower.value() + socPower.value()) / 1000000; return true; } @@ -385,23 +363,20 @@ static bool get_cpu_power_zenergy(CPUPowerData* cpuPowerData, float& power) { if (!powerData_zenergy->energyCounterFile) return false; - rewind(powerData_zenergy->energyCounterFile); - fflush(powerData_zenergy->energyCounterFile); - - uint64_t energyCounterValue = 0; - if (fscanf(powerData_zenergy->energyCounterFile, "%" SCNu64, &energyCounterValue) != 1) + auto const energyCounterValue = read_as(powerData_zenergy->energyCounterFile); + if (not energyCounterValue) return false; Clock::time_point now = Clock::now(); Clock::duration timeDiff = now - powerData_zenergy->lastCounterValueTime; int64_t timeDiffMicro = std::chrono::duration_cast(timeDiff).count(); - uint64_t energyCounterDiff = energyCounterValue - powerData_zenergy->lastCounterValue; + uint64_t energyCounterDiff = energyCounterValue.value() - powerData_zenergy->lastCounterValue; if (powerData_zenergy->lastCounterValue > 0 && energyCounterValue > powerData_zenergy->lastCounterValue) power = (float) energyCounterDiff / (float) timeDiffMicro; - powerData_zenergy->lastCounterValue = energyCounterValue; + powerData_zenergy->lastCounterValue = energyCounterValue.value(); powerData_zenergy->lastCounterValueTime = now; return true; @@ -413,22 +388,19 @@ static bool get_cpu_power_rapl(CPUPowerData* cpuPowerData, float& power) { if (!powerData_rapl->energyCounterFile) return false; - rewind(powerData_rapl->energyCounterFile); - fflush(powerData_rapl->energyCounterFile); - - uint64_t energyCounterValue = 0; - if (fscanf(powerData_rapl->energyCounterFile, "%" SCNu64, &energyCounterValue) != 1) + auto const energyCounterValue = read_as(powerData_rapl->energyCounterFile); + if (not energyCounterValue) return false; Clock::time_point now = Clock::now(); Clock::duration timeDiff = now - powerData_rapl->lastCounterValueTime; int64_t timeDiffMicro = std::chrono::duration_cast(timeDiff).count(); - uint64_t energyCounterDiff = energyCounterValue - powerData_rapl->lastCounterValue; + uint64_t energyCounterDiff = energyCounterValue.value() - powerData_rapl->lastCounterValue; if (powerData_rapl->lastCounterValue > 0 && energyCounterValue > powerData_rapl->lastCounterValue) power = energyCounterDiff / timeDiffMicro; - powerData_rapl->lastCounterValue = energyCounterValue; + powerData_rapl->lastCounterValue = energyCounterValue.value(); powerData_rapl->lastCounterValueTime = now; return true; @@ -450,14 +422,11 @@ static bool get_cpu_power_xgene(CPUPowerData* cpuPowerData, float& power) { if (!powerData_xgene->powerFile) return false; - rewind(powerData_xgene->powerFile); - fflush(powerData_xgene->powerFile); - - uint64_t powerValue = 0; - if (fscanf(powerData_xgene->powerFile, "%" SCNu64, &powerValue) != 1) + auto const powerValue = read_as(powerData_xgene->powerFile); + if (not powerValue) return false; - power = (float) powerValue / 1000000.0f; + power = (float) powerValue.value() / 1000000.0f; return true; } diff --git a/src/file_utils.cpp b/src/file_utils.cpp index 80e3031740..99a58d36bf 100644 --- a/src/file_utils.cpp +++ b/src/file_utils.cpp @@ -1,19 +1,25 @@ #include "file_utils.h" #include "string_utils.h" -#include -#include -#include -#include -#include -#include + #include +#include +#include #include + +#include +#include +#include +#include +#include + #include #ifndef PROCDIR #define PROCDIR "/proc" #endif +namespace fs = ghc::filesystem; + std::string read_line(const std::string& filename) { std::string line; diff --git a/src/file_utils.h b/src/file_utils.h index 864f0b02fa..7b287e660f 100644 --- a/src/file_utils.h +++ b/src/file_utils.h @@ -2,12 +2,11 @@ #ifndef MANGOHUD_FILE_UTILS_H #define MANGOHUD_FILE_UTILS_H +#include +#include +#include #include #include -#include -#include -#include -namespace fs = ghc::filesystem; enum LS_FLAGS { @@ -31,4 +30,28 @@ bool lib_loaded(const std::string& lib, pid_t pid); std::string remove_parentheses(const std::string&); std::string to_lower(const std::string& str); + +namespace detail { + + // using template specialization to let the compiler figure it out + template const char* type_to_fmt(); + template<> inline const char* type_to_fmt() { return "%d"; } + template<> inline const char* type_to_fmt() { return "%" PRIi64; } + template<> inline const char* type_to_fmt() { return "%" SCNi64; } + template<> inline const char* type_to_fmt() { return "%f"; } + template<> inline const char* type_to_fmt() { return "%lf"; } + +} + +/** Read a single value from sysfs file */ +template +std::optional read_as(FILE* f) { + rewind(f); + fflush(f); + ValueType v; + if (fscanf(f, detail::type_to_fmt(), &v) != 1) + return {}; + return v; +} + #endif //MANGOHUD_FILE_UTILS_H