Create sensor for all RAPLs. - energy - measure energy usage | |
git clone git://bitreich.org/energy git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit e7b10a359ff7396defb7e36dfe9f78b3c9d73b13 | |
parent 3b9da8cb1c2fcacd4570f25d02194124e526caa2 | |
Author: Troels Henriksen <[email protected]> | |
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(-) | |
--- | |
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… | |
+ 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 = |