// SPDX-License-Identifier: GPL-3.0-or-later
#include "plugin_proc.h"
#define PLUGIN_PROC_MODULE_STAT_NAME "/proc/stat"
struct per_core_single_number_file {
unsigned char found:1;
const char *filename;
int fd;
collected_number value;
RRDDIM *rd;
};
struct last_ticks {
collected_number frequency;
collected_number ticks;
};
// This is an extension of struct per_core_single_number_file at CPU_FREQ_INDEX.
// Either scaling_cur_freq or time_in_state file is used at one time.
struct per_core_time_in_state_file {
const char *filename;
procfile *ff;
size_t last_ticks_len;
struct last_ticks *last_ticks;
};
#define CORE_THROTTLE_COUNT_INDEX 0
#define PACKAGE_THROTTLE_COUNT_INDEX 1
#define CPU_FREQ_INDEX 2
#define PER_CORE_FILES 3
struct cpu_chart {
const char *id;
RRDSET *st;
RRDDIM *rd_user;
RRDDIM *rd_nice;
RRDDIM *rd_system;
RRDDIM *rd_idle;
RRDDIM *rd_iowait;
RRDDIM *rd_irq;
RRDDIM *rd_softirq;
RRDDIM *rd_steal;
RRDDIM *rd_guest;
RRDDIM *rd_guest_nice;
struct per_core_single_number_file files[PER_CORE_FILES];
struct per_core_time_in_state_file time_in_state_files;
};
static int keep_per_core_fds_open = CONFIG_BOOLEAN_YES;
static int keep_cpuidle_fds_open = CONFIG_BOOLEAN_YES;
static int read_per_core_files(struct cpu_chart *all_cpu_charts, size_t len, size_t index) {
char buf[50 + 1];
size_t x, files_read = 0, files_nonzero = 0;
for(x = 0; x < len ; x++) {
struct per_core_single_number_file *f = &all_cpu_charts[x].files[index];
f->found = 0;
if(unlikely(!f->filename))
continue;
if(unlikely(f->fd == -1)) {
f->fd = open(f->filename, O_RDONLY);
if (unlikely(f->fd == -1)) {
error("Cannot open file '%s'", f->filename);
continue;
}
}
ssize_t ret = read(f->fd, buf, 50);
if(unlikely(ret < 0)) {
// cannot read that file
error("Cannot read file '%s'", f->filename);
close(f->fd);
f->fd = -1;
continue;
}
else {
// successful read
// terminate the buffer
buf[ret] = '\0';
if(unlikely(keep_per_core_fds_open != CONFIG_BOOLEAN_YES)) {
close(f->fd);
f->fd = -1;
}
else if(lseek(f->fd, 0, SEEK_SET) == -1) {
error("Cannot seek in file '%s'", f->filename);
close(f->fd);
f->fd = -1;
}
}
files_read++;
f->found = 1;
f->value = str2ll(buf, NULL);
if(likely(f->value != 0))
files_nonzero++;
}
if