#include #include #include #include #include #include namespace cpu { void detectHwmon(cpuSensors* target, const std::string& pci) { const std::string path = "/sys/bus/pci/devices/" + pci + "/hwmon"; try { target->hwmon = utils::getFirstDir(path); } catch (...) { applog(LOG::ERR, "NO CPU HWMON KERNEL MODULE DETECTED"); return; } target->zenpower = utils::fileExists(target->hwmon+ "/in1_input"); // idk if this is reliable, we're trying to avoid just reading the name applog(LOG::INF, "Detected module \"{}\" in path \"{}\"", target->zenpower ? "zenpower" : "k10temp", target->hwmon); } void update(cpuSensors* c) { static char buf[32]; struct EnergyTs { uint64_t energy = 0; std::chrono::time_point ts; }; static EnergyTs prev; EnergyTs curr; // read power from intel-rapl? works on amd too, btop uses this trick, seems accurate // it tracks with "socket power" in hwinfo on windows, its actually the same thing i had in lcdsmartie curr.ts = std::chrono::steady_clock::now(); utils::fastReadNum("/sys/class/powercap/intel-rapl:0/energy_uj", buf, curr.energy); c->ptotal = static_cast(curr.energy - prev.energy) / static_cast(std::chrono::duration_cast(curr.ts - prev.ts).count()); prev = curr; // lots of reads but still faster than reading /proc/cpuinfo c->avg_freq = 0; for (uint8_t i = 0; i < N_CPU; i++) { utils::readFile("/sys/devices/system/cpu/cpu" + std::to_string(i) + "/cpufreq/cpuinfo_avg_freq", buf, sizeof(buf)); c->avg_freq += strtol(buf, nullptr, 10) / 1000; } c->avg_freq /= N_CPU; if (c->hwmon.empty()) return; // break if no module // commented out unused values so its faster if (c->zenpower) { utils::fastReadNum<1000>(c->hwmon + "/temp1_input", buf, c->tdie); utils::fastReadNum<1000>(c->hwmon + "/temp2_input", buf, c->tctl); utils::fastReadNum<1000>(c->hwmon + "/temp3_input", buf, c->tccd1); utils::fastReadNum<1000>(c->hwmon + "/in1_input", buf, c->vcore); utils::fastReadNum<1000>(c->hwmon + "/in2_input", buf, c->vsoc); } else { utils::fastReadNum<1000>(c->hwmon + "/temp1_input", buf, c->tctl); utils::fastReadNum<1000>(c->hwmon + "/temp3_input", buf, c->tccd1); } } } // namespace cpu