Create sensor for all RAPLs. - energy - measure energy usage HTML git clone git://bitreich.org/energy git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/energy DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit e7b10a359ff7396defb7e36dfe9f78b3c9d73b13 DIR parent 3b9da8cb1c2fcacd4570f25d02194124e526caa2 HTML Author: Troels Henriksen <athas@sigkill.dk> Date: Thu, 24 Aug 2023 16:59:46 +0200 Create sensor for all RAPLs. Diffstat: M energy.c | 79 +++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 20 deletions(-) --- DIR diff --git a/energy.c b/energy.c @@ -16,14 +16,27 @@ // // https://www.kernel.org/doc/html/latest/power/power_supply_class.html +#include <assert.h> +#include <dirent.h> #include <errno.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/wait.h> #include <sys/stat.h> +#include <sys/wait.h> #include <unistd.h> -#include <assert.h> + +// Allocates and returns a string of appropriate size. +static char* strprintf(const char *s, ...) { + va_list vl; + va_start(vl, s); + size_t needed = 1 + (size_t)vsnprintf(NULL, 0, s, vl); + char *buffer = (char*) malloc(needed); + va_start(vl, s); // Must re-init. + vsnprintf(buffer, needed, s, vl); + return buffer; +} struct sensor { const char *name; @@ -45,9 +58,6 @@ void add_sensor(struct sensor s) { sensors[num_sensors++] = s; } -const char *rapl_energy_uj = - "/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj"; - long long_from_file(const char *fname) { FILE *f = fopen(fname, "r"); if (f == NULL) { @@ -64,32 +74,61 @@ long long_from_file(const char *fname) { } } +struct rapl { + long counter; + char* energy_uj; +}; + void sensor_rapl_start(void* data) { - *(long*)data = long_from_file(rapl_energy_uj); + struct rapl* rapl = (struct rapl*)data; + rapl->counter = long_from_file(rapl->energy_uj); } void sensor_rapl_end(void* data) { - *(long*)data = long_from_file(rapl_energy_uj) - *(long*)data; + struct rapl* rapl = (struct rapl*)data; + rapl->counter = long_from_file(rapl->energy_uj) - rapl->counter; } double sensor_rapl_usage(void* data) { + struct rapl* rapl = (struct rapl*)data; // Convert microjoules to joules. - return (double)*(long*)data / 1e6; + return (double)rapl->counter / 1e6; } -void sensor_rapl(void) { - FILE *f = fopen(rapl_energy_uj, "r"); - if (f == NULL) { - fprintf(stderr, "%s: %s\n", rapl_energy_uj, strerror(errno)); - } else { - fclose(f); - long* start = malloc(sizeof(long)); - add_sensor((struct sensor) { .name = "RAPL0", - .data = start, - .start = sensor_rapl_start, - .end = sensor_rapl_end, - .usage = sensor_rapl_usage}); +void sensor_rapl() { + const char* rapl_path = "/sys/class/powercap/intel-rapl"; + DIR* d = opendir(rapl_path); + + if (d == NULL) { + return; } + + struct dirent* dirent; + + while ((dirent = readdir(d)) != NULL) { + if (dirent->d_type == DT_DIR) { + char* rapl_energy_uj = strprintf("%s/%s/energy_uj", rapl_path, dirent->d_name); + errno = 0; + FILE *f = fopen(rapl_energy_uj, "r"); + if (f == NULL) { + if (errno != ENOENT) { + fprintf(stderr, "%s: %s\n", rapl_energy_uj, strerror(errno)); + } + free(rapl_energy_uj); + } else { + fclose(f); + struct rapl *rapl = malloc(sizeof(struct rapl)); + rapl->energy_uj = rapl_energy_uj; + add_sensor((struct sensor) { .name = strdup(dirent->d_name), + .data = rapl, + .start = sensor_rapl_start, + .end = sensor_rapl_end, + .usage = sensor_rapl_usage}); + } + } + } + + closedir(d); } const char *battery_status =