From 3833c9be6bd68b2053c40eecf42dadc5afd001d8 Mon Sep 17 00:00:00 2001 From: drath Date: Sun, 10 May 2026 00:48:17 +0200 Subject: [PATCH] cpu ready? --- include/cpu.h | 3 +++ src/cpu.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/include/cpu.h b/include/cpu.h index f7ad5b6..1247bdb 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -24,4 +24,7 @@ struct cpu_sensors_t { char hwmon[128]; }; +void cpu_detect(struct cpu_sensors_t* t, const char* pci_dev); +void cpu_update(struct cpu_sensors_t *c); + #endif diff --git a/src/cpu.c b/src/cpu.c index 087385a..67e56bf 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1,8 +1,75 @@ #include "cpu.h" +#include "utils.h" +#include "log.h" #include +#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); + if (ret != 0) { + memset(t->hwmon, '\0', sizeof(t->hwmon)); + applog(LOG_WRN, "Detected %d cores, module enum #%d. Can't get hwmon path, skipping", t->num_cores, t->module); + return; + } + + char buf[128]; + char *nt = stpncpy(buf, t->hwmon, sizeof(buf)); // nt is a pointer to the null terminator of the copied string + stpcpy(nt, "/in1_input"); // write at the null terminator address + t->module = file_exists(buf) ? zenpower : k10temp; // 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)((curr.ts.tv_nsec - prev.ts.tv_nsec) / 1000); + prev = curr; + + // 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; + + // 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); + } + + 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); + } -void cpu_detect(struct cpu_sensors_t* t, const char* pci_dev) { - char path[128]; - snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/hwmon", pci_dev); } \ No newline at end of file