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 =