summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2024-03-30 13:47:10 +0100
committercgzones <cgzones@googlemail.com>2024-04-05 19:27:07 +0200
commita782ef357067962f60580478067f4023facab6a0 (patch)
tree92db47f375ba4f1c4ab5e862bc72429cedb0b015
parent15b4bc45b2b0ccf2d93164b2b1b05fb94cc89220 (diff)
linux: move libnl code into separate file
Move all the code using libnl functionality into a separate file to ease modifications. No functional change.
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac1
-rw-r--r--linux/LibNl.c123
-rw-r--r--linux/LibNl.h18
-rw-r--r--linux/LinuxProcessTable.c119
5 files changed, 153 insertions, 113 deletions
diff --git a/Makefile.am b/Makefile.am
index 0d95e370..ca2f90ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -214,6 +214,11 @@ linux_platform_sources = \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c
+if HAVE_DELAYACCT
+linux_platform_headers += linux/LibNl.h
+linux_platform_sources += linux/LibNl.c
+endif
+
if HTOP_LINUX
AM_LDFLAGS += -rdynamic
myhtopplatheaders = $(linux_platform_headers)
diff --git a/configure.ac b/configure.ac
index 8c9e484a..b3137dec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -692,6 +692,7 @@ case "$enable_delayacct" in
AC_MSG_ERROR([bad value '$enable_delayacct' for --enable-delayacct])
;;
esac
+AM_CONDITIONAL([HAVE_DELAYACCT], [test "$enable_delayacct" = yes])
AC_ARG_ENABLE([sensors],
diff --git a/linux/LibNl.c b/linux/LibNl.c
new file mode 100644
index 00000000..e61b14f6
--- /dev/null
+++ b/linux/LibNl.c
@@ -0,0 +1,123 @@
+/*
+htop - linux/LibNl.c
+(C) 2024 htop dev team
+Released under the GNU GPLv2+, see the COPYING file
+in the source distribution for its full text.
+*/
+
+#include "config.h" // IWYU pragma: keep
+
+#ifndef HAVE_DELAYACCT
+#error Compiling this file requires HAVE_DELAYACCT
+#endif
+
+#include "linux/LibNl.h"
+
+#include <linux/netlink.h>
+#include <linux/taskstats.h>
+
+#include <netlink/attr.h>
+#include <netlink/handlers.h>
+#include <netlink/msg.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+
+
+static void initNetlinkSocket(LinuxProcessTable* this) {
+ this->netlink_socket = nl_socket_alloc();
+ if (this->netlink_socket == NULL) {
+ return;
+ }
+ if (nl_connect(this->netlink_socket, NETLINK_GENERIC) < 0) {
+ return;
+ }
+ this->netlink_family = genl_ctrl_resolve(this->netlink_socket, TASKSTATS_GENL_NAME);
+}
+
+void LibNl_destroyNetlinkSocket(LinuxProcessTable* this) {
+ if (!this->netlink_socket)
+ return;
+
+ nl_close(this->netlink_socket);
+ nl_socket_free(this->netlink_socket);
+ this->netlink_socket = NULL;
+}
+
+static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) {
+ struct nlmsghdr* nlhdr;
+ struct nlattr* nlattrs[TASKSTATS_TYPE_MAX + 1];
+ const struct nlattr* nlattr;
+ struct taskstats stats;
+ int rem;
+ LinuxProcess* lp = (LinuxProcess*) linuxProcess;
+
+ nlhdr = nlmsg_hdr(nlmsg);
+
+ if (genlmsg_parse(nlhdr, 0, nlattrs, TASKSTATS_TYPE_MAX, NULL) < 0) {
+ return NL_SKIP;
+ }
+
+ if ((nlattr = nlattrs[TASKSTATS_TYPE_AGGR_PID]) || (nlattr = nlattrs[TASKSTATS_TYPE_NULL])) {
+ memcpy(&stats, nla_data(nla_next(nla_data(nlattr), &rem)), sizeof(stats));
+ assert(Process_getPid(&lp->super) == (pid_t)stats.ac_pid);
+
+ // The xxx_delay_total values wrap around on overflow.
+ // (Linux Kernel "Documentation/accounting/taskstats-struct.rst")
+ unsigned long long int timeDelta = stats.ac_etime * 1000 - lp->delay_read_time;
+ #define DELTAPERC(x, y) (timeDelta ? MINIMUM((float)((x) - (y)) / timeDelta * 100.0f, 100.0f) : NAN)
+ lp->cpu_delay_percent = DELTAPERC(stats.cpu_delay_total, lp->cpu_delay_total);
+ lp->blkio_delay_percent = DELTAPERC(stats.blkio_delay_total, lp->blkio_delay_total);
+ lp->swapin_delay_percent = DELTAPERC(stats.swapin_delay_total, lp->swapin_delay_total);
+ #undef DELTAPERC
+
+ lp->swapin_delay_total = stats.swapin_delay_total;
+ lp->blkio_delay_total = stats.blkio_delay_total;
+ lp->cpu_delay_total = stats.cpu_delay_total;
+ lp->delay_read_time = stats.ac_etime * 1000;
+ }
+ return NL_OK;
+}
+
+void LibNl_readDelayAcctData(LinuxProcessTable* this, LinuxProcess* process) {
+ struct nl_msg* msg;
+
+ if (!this->netlink_socket) {
+ initNetlinkSocket(this);
+ if (!this->netlink_socket) {
+ goto delayacct_failure;
+ }
+ }
+
+ if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) {
+ goto delayacct_failure;
+ }
+
+ if (! (msg = nlmsg_alloc())) {
+ goto delayacct_failure;
+ }
+
+ if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) {
+ nlmsg_free(msg);
+ }
+
+ if (nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, Process_getPid(&process->super)) < 0) {
+ nlmsg_free(msg);
+ }
+
+ if (nl_send_sync(this->netlink_socket, msg) < 0) {
+ goto delayacct_failure;
+ }
+
+ if (nl_recvmsgs_default(this->netlink_socket) < 0) {
+ goto delayacct_failure;
+ }
+
+ return;
+
+delayacct_failure:
+ process->swapin_delay_percent = NAN;
+ process->blkio_delay_percent = NAN;
+ process->cpu_delay_percent = NAN;
+}
diff --git a/linux/LibNl.h b/linux/LibNl.h
new file mode 100644
index 00000000..e89c3694
--- /dev/null
+++ b/linux/LibNl.h
@@ -0,0 +1,18 @@
+#ifndef HEADER_LibNl
+#define HEADER_LibNl
+/*
+htop - linux/LibNl.h
+(C) 2024 htop dev team
+Released under the GNU GPLv2+, see the COPYING file
+in the source distribution for its full text.
+*/
+
+#include "linux/LinuxProcess.h"
+#include "linux/LinuxProcessTable.h"
+
+
+void LibNl_destroyNetlinkSocket(LinuxProcessTable* this);
+
+void LibNl_readDelayAcctData(LinuxProcessTable* this, LinuxProcess* process);
+
+#endif /* HEADER_LibNl */
diff --git a/linux/LinuxProcessTable.c b/linux/LinuxProcessTable.c
index 428199d2..9a5ffdb4 100644
--- a/linux/LinuxProcessTable.c
+++ b/linux/LinuxProcessTable.c
@@ -23,18 +23,6 @@ in the source distribution for its full text.
#include <unistd.h>
#include <sys/stat.h>
-#ifdef HAVE_DELAYACCT
-#include <linux/netlink.h>
-#include <linux/taskstats.h>
-#include <netlink/attr.h>
-#include <netlink/handlers.h>
-#include <netlink/msg.h>
-#include <netlink/netlink.h>
-#include <netlink/socket.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/ctrl.h>
-#endif
-
#include "Compat.h"
#include "Hashtable.h"
#include "Machine.h"
@@ -55,6 +43,10 @@ in the source distribution for its full text.
#include "linux/LinuxProcess.h"
#include "linux/Platform.h" // needed for GNU/hurd to get PATH_MAX // IWYU pragma: keep
+#ifdef HAVE_DELAYACCT
+#include "linux/LibNl.h"
+#endif
+
#if defined(MAJOR_IN_MKDEV)
#include <sys/mkdev.h>
#elif defined(MAJOR_IN_SYSMACROS)
@@ -187,21 +179,6 @@ static void LinuxProcessTable_initTtyDrivers(LinuxProcessTable* this) {
this->ttyDrivers = ttyDrivers;
}
-#ifdef HAVE_DELAYACCT
-
-static void LinuxProcessTable_initNetlinkSocket(LinuxProcessTable* this) {
- this->netlink_socket = nl_socket_alloc();
- if (this->netlink_socket == NULL) {
- return;
- }
- if (nl_connect(this->netlink_socket, NETLINK_GENERIC) < 0) {
- return;
- }
- this->netlink_family = genl_ctrl_resolve(this->netlink_socket, TASKSTATS_GENL_NAME);
-}
-
-#endif
-
ProcessTable* ProcessTable_new(Machine* host, Hashtable* pidMatchList) {
LinuxProcessTable* this = xCalloc(1, sizeof(LinuxProcessTable));
Object_setClass(this, Class(ProcessTable));
@@ -227,10 +204,7 @@ void ProcessTable_delete(Object* cast) {
free(this->ttyDrivers);
}
#ifdef HAVE_DELAYACCT
- if (this->netlink_socket) {
- nl_close(this->netlink_socket);
- nl_socket_free(this->netlink_socket);
- }
+ LibNl_destroyNetlinkSocket(this);
#endif
free(this);
}
@@ -1010,87 +984,6 @@ static void LinuxProcessTable_readCwd(LinuxProcess* process, openat_arg_t procFd
free_and_xStrdup(&process->super.procCwd, pathBuffer);
}
-#ifdef HAVE_DELAYACCT
-
-static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) {
- struct nlmsghdr* nlhdr;
- struct nlattr* nlattrs[TASKSTATS_TYPE_MAX + 1];
- const struct nlattr* nlattr;
- struct taskstats stats;
- int rem;
- LinuxProcess* lp = (LinuxProcess*) linuxProcess;
-
- nlhdr = nlmsg_hdr(nlmsg);
-
- if (genlmsg_parse(nlhdr, 0, nlattrs, TASKSTATS_TYPE_MAX, NULL) < 0) {
- return NL_SKIP;
- }
-
- if ((nlattr = nlattrs[TASKSTATS_TYPE_AGGR_PID]) || (nlattr = nlattrs[TASKSTATS_TYPE_NULL])) {
- memcpy(&stats, nla_data(nla_next(nla_data(nlattr), &rem)), sizeof(stats));
- assert(Process_getPid(&lp->super) == (pid_t)stats.ac_pid);
-
- // The xxx_delay_total values wrap around on overflow.
- // (Linux Kernel "Documentation/accounting/taskstats-struct.rst")
- unsigned long long int timeDelta = stats.ac_etime * 1000 - lp->delay_read_time;
- #define DELTAPERC(x, y) (timeDelta ? MINIMUM((float)((x) - (y)) / timeDelta * 100.0f, 100.0f) : NAN)
- lp->cpu_delay_percent = DELTAPERC(stats.cpu_delay_total, lp->cpu_delay_total);
- lp->blkio_delay_percent = DELTAPERC(stats.blkio_delay_total, lp->blkio_delay_total);
- lp->swapin_delay_percent = DELTAPERC(stats.swapin_delay_total, lp->swapin_delay_total);
- #undef DELTAPERC
-
- lp->swapin_delay_total = stats.swapin_delay_total;
- lp->blkio_delay_total = stats.blkio_delay_total;
- lp->cpu_delay_total = stats.cpu_delay_total;
- lp->delay_read_time = stats.ac_etime * 1000;
- }
- return NL_OK;
-}
-
-static void LinuxProcessTable_readDelayAcctData(LinuxProcessTable* this, LinuxProcess* process) {
- struct nl_msg* msg;
-
- if (!this->netlink_socket) {
- LinuxProcessTable_initNetlinkSocket(this);
- if (!this->netlink_socket) {
- goto delayacct_failure;
- }
- }
-
- if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) {
- goto delayacct_failure;
- }
-
- if (! (msg = nlmsg_alloc())) {
- goto delayacct_failure;
- }
-
- if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) {
- nlmsg_free(msg);
- }
-
- if (nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, Process_getPid(&process->super)) < 0) {
- nlmsg_free(msg);
- }
-
- if (nl_send_sync(this->netlink_socket, msg) < 0) {
- goto delayacct_failure;
- }
-
- if (nl_recvmsgs_default(this->netlink_socket) < 0) {
- goto delayacct_failure;
- }
-
- return;
-
-delayacct_failure:
- process->swapin_delay_percent = NAN;
- process->blkio_delay_percent = NAN;
- process->cpu_delay_percent = NAN;
-}
-
-#endif
-
static bool LinuxProcessTable_readCmdlineFile(Process* process, openat_arg_t procFd) {
char filename[MAX_NAME + 1];
ssize_t amtRead;
@@ -1593,7 +1486,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
#ifdef HAVE_DELAYACCT
if (ss->flags & PROCESS_FLAG_LINUX_DELAYACCT) {
- LinuxProcessTable_readDelayAcctData(this, lp);
+ LibNl_readDelayAcctData(this, lp);
}
#endif

© 2014-2024 Faster IT GmbH | imprint | privacy policy