#include "cpu.h" #include "log.h" #include "utils.h" #include #include #include void cpu_detect(struct cpu_sensors_t *t, const char *pci_dev) { t->module = unknown; t->num_cores = sysconf(_SC_NPROCESSORS_ONLN); snprintf(t->hwmon, sizeof(t->hwmon), "/sys/bus/pci/devices/%s/hwmon", pci_dev); const int ret = get_hwmon_dir(t->hwmon, sizeof(t->hwmon)); if (ret != 0) { t->hwmon[0] = '\0'; applog(LOG_WRN, "Detected %d cores, module enum #%d. Can't get hwmon path, skipping", t->num_cores, t->module); return; } t->module = read_file(t->hwmon, "/in1_input", nullptr, 0) ? zenpower : k10temp; // if we can read zenpower file then zenpower. idk if this is reliable, we're trying to avoid just reading the name applog(LOG_INF, "Detected %d cores, module enum #%d in path %s", t->num_cores, t->module, t->hwmon); } void cpu_update(struct cpu_sensors_t *c) { static char buf[32]; struct energy_t { struct timespec ts; uint64_t energy; }; static struct energy_t prev; struct energy_t 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 clock_gettime(CLOCK_MONOTONIC, &curr.ts); fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "energy_uj", buf, &curr.energy, 1); c->ptotal = (float)(curr.energy - prev.energy) / (float)timespec_diff_us(&curr.ts, &prev.ts); prev = curr; if (c->ptotal > 500.0f || c->ptotal < 0.0f) c->ptotal = 0.0f; // lots of reads but still faster than reading /proc/cpuinfo c->avg_freq = 0; char p[128]; for (uint8_t i = 0; i < c->num_cores; i++) { uint64_t t = 0; sprintf(p, "/sys/devices/system/cpu/cpu%d/cpufreq/", i); fast_read_num_u64(p, "cpuinfo_avg_freq", buf, &t, 1000); c->avg_freq += t; } c->avg_freq /= (c->num_cores > 1) ? c->num_cores : 1; if (c->module == unknown) return; if (c->module == k10temp) { fast_read_num_i16(c->hwmon, "/temp1_input", buf, &c->tctl, 1000); fast_read_num_i16(c->hwmon, "/temp3_input", buf, &c->tccd1, 1000); } // commented out unused values so its faster if (c->module == zenpower) { fast_read_num_i16(c->hwmon, "/temp1_input", buf, &c->tdie, 1000); fast_read_num_i16(c->hwmon, "/temp2_input", buf, &c->tctl, 1000); fast_read_num_i16(c->hwmon, "/temp3_input", buf, &c->tccd1, 1000); // utils::fastReadNum<1000>(c->hwmon + "/in1_input", buf, c->vcore); // utils::fastReadNum<1000>(c->hwmon + "/in2_input", buf, c->vsoc); } }