X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcpufreq.c;h=35ec07fbc98c3ef798f200972310a1967ca5d08f;hb=06ad08cb970cc55711cdca968f79f90610dbbf58;hp=6c2689ffceab317be88076a70021abc7fce23c84;hpb=35b0e3f1704c9a6811443d7a4326337d94023cd9;p=collectd.git diff --git a/src/cpufreq.c b/src/cpufreq.c index 6c2689ff..35ec07fb 100644 --- a/src/cpufreq.c +++ b/src/cpufreq.c @@ -22,8 +22,8 @@ #include "collectd.h" -#include "common.h" #include "plugin.h" +#include "utils/common/common.h" #define MAX_AVAIL_FREQS 20 @@ -37,7 +37,7 @@ struct cpu_data_t { static bool report_p_stats = false; static void cpufreq_stats_init(void) { - cpu_data = calloc(num_cpu, sizeof(struct cpu_data_t)); + cpu_data = calloc(num_cpu, sizeof(*cpu_data)); if (cpu_data == NULL) return; @@ -116,6 +116,75 @@ static void cpufreq_submit(int cpu_num, const char *type, plugin_dispatch_values(&vl); } +static void cpufreq_read_stats(int cpu) { + char filename[PATH_MAX]; + /* Read total transitions for cpu frequency */ + snprintf(filename, sizeof(filename), + "/sys/devices/system/cpu/cpu%d/cpufreq/stats/total_trans", cpu); + + value_t v; + if (parse_value_file(filename, &v, DS_TYPE_DERIVE) != 0) { + ERROR("cpufreq plugin: Reading \"%s\" failed.", filename); + return; + } + cpufreq_submit(cpu, "transitions", NULL, &v); + + /* Determine percentage time in each state for cpu during previous + * interval. */ + snprintf(filename, sizeof(filename), + "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu); + + FILE *fh = fopen(filename, "r"); + if (fh == NULL) { + ERROR("cpufreq plugin: Reading \"%s\" failed.", filename); + return; + } + + int state_index = 0; + cdtime_t now = cdtime(); + char buffer[DATA_MAX_NAME_LEN]; + + while (fgets(buffer, sizeof(buffer), fh) != NULL) { + unsigned int frequency; + unsigned long long time; + + /* + * State time units is 10ms. To get rate of seconds per second + * we have to divide by 100. To get percents we have to multiply it + * by 100 back. So, just use parsed value directly. + */ + if (!sscanf(buffer, "%u%llu", &frequency, &time)) { + ERROR("cpufreq plugin: Reading \"%s\" failed.", filename); + break; + } + + char state[DATA_MAX_NAME_LEN]; + snprintf(state, sizeof(state), "%u", frequency); + + 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 " + "this.", + (state_index + 1), MAX_AVAIL_FREQS); + break; + } + + gauge_t g; + if (value_to_rate(&g, (value_t){.derive = time}, DS_TYPE_DERIVE, now, + &(cpu_data[cpu].time_state[state_index])) == 0) { + /* + * Due to some inaccuracy reported value can be a bit greatrer than 100.1. + * That produces gaps on charts. + */ + if (g > 100.1) + g = 100.1; + cpufreq_submit(cpu, "percent", state, &(value_t){.gauge = g}); + } + state_index++; + } + fclose(fh); +} + static int cpufreq_read(void) { for (int cpu = 0; cpu < num_cpu; cpu++) { char filename[PATH_MAX]; @@ -134,66 +203,8 @@ static int cpufreq_read(void) { cpufreq_submit(cpu, "cpufreq", NULL, &v); - if (report_p_stats) { - /* Read total transitions for cpu frequency */ - snprintf(filename, sizeof(filename), - "/sys/devices/system/cpu/cpu%d/cpufreq/stats/total_trans", cpu); - if (parse_value_file(filename, &v, DS_TYPE_COUNTER) != 0) { - ERROR("cpufreq plugin: Reading \"%s\" failed.", filename); - continue; - } - cpufreq_submit(cpu, "counter", "transitions", &v); - - /* Determine percentage time in each state for cpu during previous - * interval. */ - snprintf(filename, sizeof(filename), - "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", - cpu); - - FILE *fh = fopen(filename, "r"); - if (fh == NULL) { - ERROR("cpufreq plugin: Reading \"%s\" failed.", filename); - continue; - } - - int state_index = 0; - cdtime_t now = cdtime(); - char buffer[DATA_MAX_NAME_LEN]; - - while (fgets(buffer, sizeof(buffer), fh) != NULL) { - unsigned int frequency; - unsigned long long time; - - /* - * State time units is 10ms. To get rate of seconds per second - * we have to divide by 100. To get percents we have to multiply it - * by 100 back. So, just use parsed value directly. - */ - if (!sscanf(buffer, "%u%llu", &frequency, &time)) { - ERROR("cpufreq plugin: Reading \"%s\" failed.", filename); - break; - } - - char state[DATA_MAX_NAME_LEN]; - snprintf(state, sizeof(state), "%u", frequency); - - if (state_index >= MAX_AVAIL_FREQS) { - NOTICE("cpufreq plugin: Found too much frequency states (%d > %d). " - "Plugin needs to be recompiled. Please open a bug report for " - "this.", - (state_index + 1), MAX_AVAIL_FREQS); - break; - } - - gauge_t g; - if (value_to_rate(&g, (value_t){.counter = time}, DS_TYPE_COUNTER, now, - &(cpu_data[cpu].time_state[state_index])) == 0) { - cpufreq_submit(cpu, "percent", state, &(value_t){.gauge = g}); - } - state_index++; - } - fclose(fh); - } + if (report_p_stats) + cpufreq_read_stats(cpu); } return 0; } /* int cpufreq_read */