]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
src/cpufreq.c: Importing changes from `main`.
authorFlorian Forster <octo@collectd.org>
Tue, 19 Dec 2023 08:51:54 +0000 (09:51 +0100)
committerFlorian Forster <octo@collectd.org>
Mon, 22 Jan 2024 20:22:04 +0000 (21:22 +0100)
Changes:
5332f432633fb62fcd03b2540734b17e5785ab90 cpufreq: init max_avail_freqs with 128
d760819acbdc9a51c65b52c32cacec3ee9b991aa cpufreq: dynamically alloc max_avail_freqs according to time_in_state
45b676685b2a56545359c6b76985f95a56b99e72 cpufreq: format.sh cpufreq.c
31dbb8a334f9501662326496171f6cffd18bd92a cpufreq: make MAX_AVAIL_FREQS configurable in conf

src/cpufreq.c

index f95b2828a5246806476fc3626809b4457692683c..befbb647d3fa16ec523adfb5de6bf0629e45cc06 100644 (file)
 #endif
 
 #if KERNEL_LINUX
-#define MAX_AVAIL_FREQS 20
+static int max_avail_freqs = 128; // default MAX_AVAIL_FREQS
 
 static int num_cpu;
 
 struct cpu_data_t {
-  value_to_rate_state_t time_state[MAX_AVAIL_FREQS];
+  value_to_rate_state_t *time_state;
 } * cpu_data;
 
 /* Flags denoting capability of reporting CPU frequency statistics. */
@@ -62,6 +62,25 @@ static void cpufreq_stats_init(void) {
              filename);
       report_p_stats = false;
       break;
+    } else {
+      /* Count the number of lines in the file content:
+       * /sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state */
+      FILE *fh = fopen(filename, "r");
+      if (fh == NULL) {
+        ERROR("cpufreq plugin: File %s not exists or no access.", filename);
+        break;
+      }
+      int state_count = 0;
+      char line[DATA_MAX_NAME_LEN] = {0};
+      while (fgets(line, sizeof(line), fh) != NULL) {
+        state_count++;
+      }
+      fclose(fh);
+
+      /* variable: max_avail_freqs, takes the maximum value of the actual
+       * statistics. */
+      max_avail_freqs =
+          state_count > max_avail_freqs ? state_count : max_avail_freqs;
     }
 
     snprintf(filename, sizeof(filename),
@@ -75,6 +94,18 @@ static void cpufreq_stats_init(void) {
       break;
     }
   }
+
+  for (int i = 0; i < num_cpu; i++) {
+    cpu_data[i].time_state =
+        calloc(max_avail_freqs, sizeof(value_to_rate_state_t));
+    if (cpu_data[i].time_state == NULL) {
+      ERROR("cpufreq plugin: time_state memory allocation failed. P-State "
+            "statistics will not be reported.");
+      report_p_stats = false;
+      return;
+    }
+  }
+
   return;
 }
 #endif /* KERNEL_LINUX */
@@ -180,11 +211,11 @@ static void cpufreq_read_stats(int cpu) {
     char state[DATA_MAX_NAME_LEN];
     snprintf(state, sizeof(state), "%u", frequency);
 
-    if (state_index >= MAX_AVAIL_FREQS) {
+    if (state_index >= max_avail_freqs) {
       NOTICE("cpufreq plugin: Found too many frequency states (%d > %d). "
-             "Plugin needs to be recompiled. Please open a bug report for "
+             "Please open a bug report for "
              "this.",
-             (state_index + 1), MAX_AVAIL_FREQS);
+             (state_index + 1), max_avail_freqs);
       break;
     }