From: Michael Tremer Date: Sun, 28 Sep 2025 10:53:00 +0000 (+0000) Subject: modules: Add context switches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=710d285903171630c1a657959d4783cdb1e4446c;p=telemetry.git modules: Add context switches Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 7587c56..330b22a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -102,6 +102,8 @@ dist_collectyd_SOURCES = \ src/daemon/module.h \ src/daemon/modules.c \ src/daemon/modules.h \ + src/daemon/modules/contextswitches.c \ + src/daemon/modules/contextswitches.h \ src/daemon/modules/loadavg.c \ src/daemon/modules/loadavg.h \ src/daemon/queue.c \ diff --git a/src/daemon/modules.c b/src/daemon/modules.c index eead382..da13f85 100644 --- a/src/daemon/modules.c +++ b/src/daemon/modules.c @@ -28,10 +28,12 @@ #include "modules.h" // Load all modules +#include "modules/contextswitches.h" #include "modules/loadavg.h" // Register all modules static const collecty_module_methods* modules[] = { + &contextswitches_module, &loadavg_module, NULL, }; diff --git a/src/daemon/modules/contextswitches.c b/src/daemon/modules/contextswitches.c new file mode 100644 index 0000000..4b1cc72 --- /dev/null +++ b/src/daemon/modules/contextswitches.c @@ -0,0 +1,133 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include +#include +#include +#include +#include + +#include "../ctx.h" +#include "../module.h" +#include "contextswitches.h" + +static int perf_event_open(struct perf_event_attr* hw_event, + pid_t pid, int cpu, int group_fd, unsigned long flags) { + return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); +} + +static unsigned int num_cpus = 0; +static int* perf_eventfds = NULL; + +static int contextswitches_init(collecty_ctx* ctx) { + struct perf_event_attr event = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_CONTEXT_SWITCHES, + .size = sizeof(event), + .disabled = 0, + .exclude_kernel = 0, + .exclude_hv = 0, + }; + int fd = -EBADF; + + // Detect the total number of processors + if (!num_cpus) + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + + // Allocate an array for the file descriptors + perf_eventfds = calloc(num_cpus, sizeof(*perf_eventfds)); + if (!perf_eventfds) + return -errno; + + // Initialize the array + for (unsigned int i = 0; i < num_cpus; i++) + perf_eventfds[i] = -EBADF; + + // Keep a perf file descriptor open for each CPU core + for (unsigned int i = 0; i < num_cpus; i++) { + fd = perf_event_open(&event, -1, i, -1, 0); + if (fd < 0) { + ERROR(ctx, "Failed run perf_event_open() for CPU %d: %m\n", i); + return -errno; + } + + // Store the file descriptor + perf_eventfds[i] = fd; + } + + return 0; +} + +static int contextswitches_free(collecty_ctx* ctx) { + // Close any open file descriptors + if (perf_eventfds) { + for (unsigned int i = 0; i < num_cpus; i++) { + if (perf_eventfds[i] >= 0) + close(perf_eventfds[i]); + } + free(perf_eventfds); + } + + return 0; +} + +static int contextswitches_collect(collecty_ctx* ctx, collecty_module* module) { + long long total = 0; + uint64_t count = 0; + int fd = -EBADF; + int r; + + // Read the number of context switches per CPU and add them up + for (unsigned int i = 0; i < num_cpus; i++) { + fd = perf_eventfds[i]; + + // Abort if we are missing some file descriptors + if (fd < 0) + return -EBADFD; + + // Read the integer + r = read(fd, &count, sizeof(count)); + if (r < 0) { + ERROR(ctx, "Failed to read the number of context switches: %m\n"); + return -errno; + } + + // Sum up all values + total += count; + } + + // Submit the values + return collecty_module_submit(module, NULL, "%lld", total); +} + +const collecty_module_methods contextswitches_module = { + .name = "contextswitches", + + // RRD Data Sources + .rrd_dss = { + { "ctxt", "DERIVE", 0, -1, }, + { NULL }, + }, + + // Methods + .init = contextswitches_init, + .free = contextswitches_free, + .collect = contextswitches_collect, +}; diff --git a/src/daemon/modules/contextswitches.h b/src/daemon/modules/contextswitches.h new file mode 100644 index 0000000..d363de6 --- /dev/null +++ b/src/daemon/modules/contextswitches.h @@ -0,0 +1,28 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#ifndef COLLECTY_MODULE_CONTEXTSWITCHES_H +#define COLLECTY_MODULE_CONTEXTSWITCHES_H + +#include "../module.h" + +extern const collecty_module_methods contextswitches_module; + +#endif /* COLLECTY_MODULE_CONTEXTSWITCHES_H */