Blame SOURCES/0004-Prepare-to-handle-thermal-event.patch

8dca8a
From b66647ab757c580b2532c117bd345d1bad3b2bd5 Mon Sep 17 00:00:00 2001
8dca8a
From: "Chang S. Bae" <chang.seok.bae@intel.com>
8dca8a
Date: Thu, 10 Feb 2022 14:46:01 -0800
8dca8a
Subject: [PATCH 04/14] Prepare to handle thermal event
8dca8a
8dca8a
Intel's new hardware supports Hardware Feedback Interface to provide CPU
8dca8a
performance and energy efficiency information. Every update on this is
8dca8a
delivered via thermal event interrupt. The thermal framework in the Linux
8dca8a
kernel relays these notifications to userspace via a Netlink interface.
8dca8a
8dca8a
When a CPU's performance and efficiency are zero, irqbalance needs to mask
8dca8a
the CPU from interrupts. Introduce a new CPU mask to indicate banned CPUs
8dca8a
for this.
8dca8a
8dca8a
Before supporting this event handling, define functions. Their
8dca8a
implementation will be on the following patches.
8dca8a
8dca8a
This event is available only on x86-64 systems. And it can be subscribed
8dca8a
with help of Netlink libraries. So check them before building it.
8dca8a
8dca8a
Also add a new build option so users may opt out this support. Setting this
8dca8a
option on other systems will result in a build failure.
8dca8a
8dca8a
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
8dca8a
---
8dca8a
 Makefile.am  |  7 +++--
8dca8a
 configure.ac | 22 ++++++++++++++
8dca8a
 cputree.c    |  6 ++++
8dca8a
 irqbalance.c |  4 +++
8dca8a
 thermal.c    | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
8dca8a
 thermal.h    | 15 ++++++++++
8dca8a
 6 files changed, 135 insertions(+), 2 deletions(-)
8dca8a
 create mode 100644 thermal.c
8dca8a
 create mode 100644 thermal.h
8dca8a
8dca8a
diff --git a/Makefile.am b/Makefile.am
8dca8a
index 84e7d46..9181a34 100644
8dca8a
--- a/Makefile.am
8dca8a
+++ b/Makefile.am
8dca8a
@@ -27,7 +27,7 @@ EXTRA_DIST = COPYING autogen.sh misc/irqbalance.service misc/irqbalance.env
8dca8a
 SUBDIRS = tests
8dca8a
 
8dca8a
 UI_DIR = ui
8dca8a
-AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS) $(NUMA_CFLAGS)
8dca8a
+AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS) $(NUMA_CFLAGS) $(LIBNL3_CFLAGS)
8dca8a
 AM_CPPFLAGS = -I${top_srcdir} -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE
8dca8a
 noinst_HEADERS = bitmap.h constants.h cpumask.h irqbalance.h non-atomic.h \
8dca8a
 	types.h $(UI_DIR)/helpers.h $(UI_DIR)/irqbalance-ui.h $(UI_DIR)/ui.h
8dca8a
@@ -39,7 +39,10 @@ endif
8dca8a
 
8dca8a
 irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
8dca8a
 	irqlist.c numa.c placement.c procinterrupts.c
8dca8a
-irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) $(NUMA_LIBS)
8dca8a
+if THERMAL
8dca8a
+irqbalance_SOURCES += thermal.c
8dca8a
+endif
8dca8a
+irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) $(NUMA_LIBS) $(LIBNL3_LIBS)
8dca8a
 if IRQBALANCEUI
8dca8a
 irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
8dca8a
 	$(UI_DIR)/ui.c
8dca8a
diff --git a/configure.ac b/configure.ac
8dca8a
index 32082fc..15532c1 100644
8dca8a
--- a/configure.ac
8dca8a
+++ b/configure.ac
8dca8a
@@ -36,6 +36,28 @@ AS_IF([test "x$has_ncursesw" = "xyes"], [
8dca8a
   AC_SUBST([LIBS])
8dca8a
 ])
8dca8a
 
8dca8a
+AC_CANONICAL_HOST
8dca8a
+
8dca8a
+AC_ARG_ENABLE(thermal,
8dca8a
+  AS_HELP_STRING([--enable-thermal], [enable thermal event support [default=auto]]),,
8dca8a
+  AS_IF([test x"$host_cpu" = x"x86_64"], [enable_thermal=yes], [enable_thermal=no])
8dca8a
+)
8dca8a
+
8dca8a
+AS_IF([test x"$enable_thermal" = x"yes" && test x"$host_cpu" != x"x86_64"],
8dca8a
+  AC_MSG_ERROR([no thermal events support on $host_cpu systems.]),
8dca8a
+)
8dca8a
+
8dca8a
+AS_IF([test x"$enable_thermal" = x"yes"],
8dca8a
+  [PKG_CHECK_MODULES([LIBNL3], [libnl-3.0 libnl-genl-3.0], [have_thermal=yes],
8dca8a
+    AC_MSG_NOTICE([no thermal event support as libnl-3.0 is unavailable.])
8dca8a
+  )]
8dca8a
+)
8dca8a
+
8dca8a
+AS_IF([test "x$have_thermal" = xyes],
8dca8a
+  AC_DEFINE([HAVE_THERMAL], 1, [Build irqbalance to support thermal events])
8dca8a
+)
8dca8a
+AM_CONDITIONAL([THERMAL], [test "x$have_thermal" = xyes])
8dca8a
+
8dca8a
 AC_C_CONST
8dca8a
 AC_C_INLINE
8dca8a
 AM_PROG_CC_C_O
8dca8a
diff --git a/cputree.c b/cputree.c
8dca8a
index b716a8f..c250977 100644
8dca8a
--- a/cputree.c
8dca8a
+++ b/cputree.c
8dca8a
@@ -38,6 +38,7 @@
8dca8a
 #include <glib.h>
8dca8a
 
8dca8a
 #include "irqbalance.h"
8dca8a
+#include "thermal.h"
8dca8a
 
8dca8a
 #ifdef HAVE_IRQBALANCEUI
8dca8a
 extern char *banned_cpumask_from_ui;
8dca8a
@@ -162,6 +163,11 @@ static void setup_banned_cpus(void)
8dca8a
 	cpumask_scnprintf(buffer, 4096, nohz_full);
8dca8a
 	log(TO_CONSOLE, LOG_INFO, "Adaptive-ticks CPUs: %s\n", buffer);
8dca8a
 out:
8dca8a
+#ifdef HAVE_THERMAL
8dca8a
+	cpus_or(banned_cpus, banned_cpus, thermal_banned_cpus);
8dca8a
+	cpumask_scnprintf(buffer, 4096, thermal_banned_cpus);
8dca8a
+	log(TO_CONSOLE, LOG_INFO, "Thermal-banned CPUs: %s\n", buffer);
8dca8a
+#endif
8dca8a
 	cpumask_scnprintf(buffer, 4096, banned_cpus);
8dca8a
 	log(TO_CONSOLE, LOG_INFO, "Banned CPUs: %s\n", buffer);
8dca8a
 }
8dca8a
diff --git a/irqbalance.c b/irqbalance.c
8dca8a
index e8d9ba9..c520c11 100644
8dca8a
--- a/irqbalance.c
8dca8a
+++ b/irqbalance.c
8dca8a
@@ -44,6 +44,7 @@
8dca8a
 #include <sys/socket.h>
8dca8a
 #endif
8dca8a
 #include "irqbalance.h"
8dca8a
+#include "thermal.h"
8dca8a
 
8dca8a
 volatile int keep_going = 1;
8dca8a
 int one_shot_mode;
8dca8a
@@ -703,6 +704,8 @@ int main(int argc, char** argv)
8dca8a
 		goto out;
8dca8a
 	}
8dca8a
 #endif
8dca8a
+	if (init_thermal())
8dca8a
+		log(TO_ALL, LOG_WARNING, "Failed to initialize thermal events.\n");
8dca8a
 	main_loop = g_main_loop_new(NULL, FALSE);
8dca8a
 	last_interval = sleep_interval;
8dca8a
 	g_timeout_add_seconds(sleep_interval, scan, NULL);
8dca8a
@@ -711,6 +714,7 @@ int main(int argc, char** argv)
8dca8a
 	g_main_loop_quit(main_loop);
8dca8a
 
8dca8a
 out:
8dca8a
+	deinit_thermal();
8dca8a
 	free_object_tree();
8dca8a
 	free_cl_opts();
8dca8a
 	free(polscript);
8dca8a
diff --git a/thermal.c b/thermal.c
8dca8a
new file mode 100644
8dca8a
index 0000000..308bc48
8dca8a
--- /dev/null
8dca8a
+++ b/thermal.c
8dca8a
@@ -0,0 +1,83 @@
8dca8a
+/*
8dca8a
+ * This program is free software; you can redistribute it and/or modify
8dca8a
+ * it under the terms of the GNU General Public License version 2 as
8dca8a
+ * published by the Free Software Foundation.
8dca8a
+ */
8dca8a
+
8dca8a
+#include <stdio.h>
8dca8a
+
8dca8a
+#include <netlink/genl/genl.h>
8dca8a
+#include <netlink/genl/family.h>
8dca8a
+#include <netlink/genl/ctrl.h>
8dca8a
+
8dca8a
+#include "irqbalance.h"
8dca8a
+
8dca8a
+cpumask_t thermal_banned_cpus;
8dca8a
+
8dca8a
+static gboolean prepare_netlink(void)
8dca8a
+{
8dca8a
+	gboolean error = TRUE;
8dca8a
+
8dca8a
+	log(TO_ALL, LOG_ERR, "thermal: not yet implement to alloc memory for netlink.\n");
8dca8a
+	return error;
8dca8a
+}
8dca8a
+
8dca8a
+#define NL_FAMILY_NAME	"nlctrl"
8dca8a
+
8dca8a
+static gboolean establish_netlink(void)
8dca8a
+{
8dca8a
+	gboolean error = TRUE;
8dca8a
+
8dca8a
+	log(TO_ALL, LOG_ERR, "thermal: not yet implemented to establish netlink.\n");
8dca8a
+	return error;
8dca8a
+}
8dca8a
+
8dca8a
+static gboolean register_netlink_handler(nl_recvmsg_msg_cb_t handler __attribute__((unused)))
8dca8a
+{
8dca8a
+	gboolean error = TRUE;
8dca8a
+
8dca8a
+	log(TO_ALL, LOG_ERR, "thermal: not yet implemented to register thermal handler.\n");
8dca8a
+	return error;
8dca8a
+}
8dca8a
+
8dca8a
+static gboolean set_netlink_nonblocking(void)
8dca8a
+{
8dca8a
+	gboolean error = TRUE;
8dca8a
+
8dca8a
+	log(TO_ALL, LOG_ERR, "thermal: not yet implemented to set nonblocking socket.\n");
8dca8a
+	return error;
8dca8a
+}
8dca8a
+
8dca8a
+void deinit_thermal(void)
8dca8a
+{
8dca8a
+	return;
8dca8a
+}
8dca8a
+
8dca8a
+/*
8dca8a
+ * return value: TRUE with an error; otherwise, FALSE
8dca8a
+ */
8dca8a
+gboolean init_thermal(void)
8dca8a
+{
8dca8a
+	gboolean error;
8dca8a
+
8dca8a
+	error = prepare_netlink();
8dca8a
+	if (error)
8dca8a
+		goto err_out;
8dca8a
+
8dca8a
+	error = establish_netlink();
8dca8a
+	if (error)
8dca8a
+		goto err_out;
8dca8a
+
8dca8a
+	error = register_netlink_handler(NULL);
8dca8a
+	if (error)
8dca8a
+		goto err_out;
8dca8a
+
8dca8a
+	error = set_netlink_nonblocking();
8dca8a
+	if (error)
8dca8a
+		goto err_out;
8dca8a
+
8dca8a
+	return FALSE;
8dca8a
+err_out:
8dca8a
+	deinit_thermal();
8dca8a
+	return TRUE;
8dca8a
+}
8dca8a
diff --git a/thermal.h b/thermal.h
8dca8a
new file mode 100644
8dca8a
index 0000000..657d54e
8dca8a
--- /dev/null
8dca8a
+++ b/thermal.h
8dca8a
@@ -0,0 +1,15 @@
8dca8a
+#ifndef __LINUX_THERMAL_H_
8dca8a
+#define __LINUX_THERMAL_H_
8dca8a
+
8dca8a
+#include <glib.h>
8dca8a
+
8dca8a
+#ifdef HAVE_THERMAL
8dca8a
+gboolean init_thermal(void);
8dca8a
+void deinit_thermal(void);
8dca8a
+extern cpumask_t thermal_banned_cpus;
8dca8a
+#else
8dca8a
+static inline gboolean init_thermal(void) { return FALSE; }
8dca8a
+#define deinit_thermal() do { } while (0)
8dca8a
+#endif
8dca8a
+
8dca8a
+#endif /* __LINUX_THERMAL_H_ */
8dca8a
-- 
8dca8a
2.33.1
8dca8a