All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yury Norov <ynorov@nvidia.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>, Thomas Gleixner <tglx@kernel.org>,
	Juri Lelli <juri.lelli@redhat.com>,
	Vincent Guittot <vincent.guittot@linaro.org>,
	Shrikanth Hegde <sshegde@linux.ibm.com>
Cc: Yury Norov <ynorov@nvidia.com>, Yury Norov <yury.norov@gmail.com>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	Alexander Gordeev <agordeev@linux.ibm.com>,
	Andrea Righi <arighi@nvidia.com>, Ben Segall <bsegall@google.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	Danilo Krummrich <dakr@kernel.org>,
	Dietmar Eggemann <dietmar.eggemann@arm.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Heiko Carstens <hca@linux.ibm.com>,
	Johan Hovold <johan@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	K Prateek Nayak <kprateek.nayak@amd.com>,
	Mel Gorman <mgorman@suse.de>, Mete Durlu <meted@linux.ibm.com>,
	Randy Dunlap <rdunlap@infradead.org>,
	Rasmus Villemoes <linux@rasmusvillemoes.dk>,
	Shuah Khan <skhan@linuxfoundation.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Sven Schnelle <svens@linux.ibm.com>,
	Valentin Schneider <vschneid@redhat.com>,
	Vasily Gorbik <gor@linux.ibm.com>,
	linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	driver-core@lists.linux.dev, linux-s390@vger.kernel.org
Subject: [PATCH 4/6] sched: serialize preferred cpumask update better
Date: Sun,  1 Nov 2026 14:22:00 -0500	[thread overview]
Message-ID: <20261101192203.6979-5-ynorov@nvidia.com> (raw)
In-Reply-To: <20261101192203.6979-1-ynorov@nvidia.com>

This series adds more flexibility to control the 'preferred' status of
CPUs, so that multiple modules may access the mask concurrently. Thus,
add the cpu_preferred_mutex.

With that, the scheme would look like this:

 - if your code takes cpus_write_lock(), it's enough to write-access
   the preferred cpumask;
 - if your code takes cpus_read_lock(), you'd also take
   cpu_preferred_mutex in order to modify the preferred mask.

This approach also fixes the existing race between steal governor
sampling and hotplug/unplug.

Fixes: 27d47ebce4d6 ("virt/steal_governor: Implement steal_governor policy loop")
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
 drivers/virt/steal_governor.c | 21 ++++++++++++++++-----
 include/linux/cpumask.h       | 15 ++++++++++++---
 kernel/cpu.c                  |  4 ++++
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/drivers/virt/steal_governor.c b/drivers/virt/steal_governor.c
index 4cd9971fec45..bc3936e69eed 100644
--- a/drivers/virt/steal_governor.c
+++ b/drivers/virt/steal_governor.c
@@ -23,6 +23,7 @@
 #include <linux/ktime.h>
 #include <linux/math64.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/sched/isolation.h>
 #include <linux/topology.h>
 #include <linux/types.h>
@@ -134,7 +135,8 @@ static void decrease_preferred_cpus(void)
 	int target_cpu = nr_cpu_ids;
 	int cpu;
 
-	guard(cpus_read_lock)();
+	lockdep_assert_cpus_held();
+	lockdep_assert_held(&cpu_preferred_mutex);
 	cpu = cpumask_first_and(housekeeping_cpumask(HK_TYPE_KERNEL_NOISE),
 				cpu_preferred_mask);
 	if (cpu >= nr_cpu_ids)
@@ -174,7 +176,8 @@ static void increase_preferred_cpus(void)
 {
 	int first_cpu, cpu;
 
-	guard(cpus_read_lock)();
+	lockdep_assert_cpus_held();
+	lockdep_assert_held(&cpu_preferred_mutex);
 	first_cpu = cpumask_first_andnot(cpu_active_mask, cpu_preferred_mask);
 
 	/* All CPUs are preferred. Nothing to increase further */
@@ -188,6 +191,9 @@ static void increase_preferred_cpus(void)
 
 static bool preferred_cpus_valid(void)
 {
+	lockdep_assert_cpus_held();
+	lockdep_assert_held(&cpu_preferred_mutex);
+
 	if (cpumask_empty(cpu_preferred_mask)) {
 		pr_err("empty preferred mask. stopping\n");
 		return false;
@@ -208,6 +214,9 @@ static void steal_governor_loop(struct work_struct *work)
 	u64 curr_steal, delta_steal, delta_ns, steal_ratio;
 	ktime_t now;
 
+	guard(cpus_read_lock)();
+	guard(mutex)(&cpu_preferred_mutex);
+
 	now = ktime_get();
 	delta_ns = ktime_to_ns(ktime_sub(now, sg_ctx.time));
 
@@ -238,8 +247,7 @@ static void steal_governor_loop(struct work_struct *work)
 	 * module restores to active if CPU hotplug breaks those assumptions.
 	 */
 	if (!preferred_cpus_valid()) {
-		scoped_guard(cpus_read_lock)
-			reset_preferred_cpumask();
+		reset_preferred_cpumask();
 		return;
 	}
 
@@ -276,8 +284,11 @@ static int __init steal_governor_init(void)
 static void __exit steal_governor_exit(void)
 {
 	disable_delayed_work_sync(&sg_ctx.work);
-	scoped_guard(cpus_read_lock)
+	scoped_guard(cpus_read_lock) {
+		guard(mutex)(&cpu_preferred_mutex);
+
 		reset_preferred_cpumask();
+	}
 	pr_info("disabled\n");
 }
 
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c65abfc8a97f..fc911a153b44 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -123,7 +123,14 @@ extern struct cpumask __cpu_active_mask;
 extern struct cpumask __cpu_dying_mask;
 
 #ifdef CONFIG_PREFERRED_CPU
+/*
+ * Drivers must take cpus_read_lock() before cpu_preferred_mutex and
+ * hold both across mask validation and updates. If cpus_write_lock()
+ * is held, it guarantees the exclusive access to the mask, thus
+ * holding cpu_preferred_mutex isn't necessary.
+ */
 extern struct cpumask __cpu_preferred_mask;
+extern struct mutex cpu_preferred_mutex;
 #else
 #define __cpu_preferred_mask __cpu_active_mask
 #endif
@@ -1199,12 +1206,14 @@ void init_cpu_possible(const struct cpumask *src);
  * reset_preferred_cpumask - reset preferred CPUs to the active mask.
  *
  * Callers must serialize against CPU hotplug and other preferred cpumask
- * writers.
+ * writers. Requires cpus_read_lock() and cpu_preferred_mutex; or
+ * cpus_write_lock().
  */
 static inline void reset_preferred_cpumask(void)
 {
-	if (IS_ENABLED(CONFIG_PREFERRED_CPU))
-		cpumask_copy(&__cpu_preferred_mask, cpu_active_mask);
+#ifdef CONFIG_PREFERRED_CPU
+	cpumask_copy(&__cpu_preferred_mask, cpu_active_mask);
+#endif
 }
 
 void set_cpu_online(unsigned int cpu, bool online);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 376d297a6292..dec08a90ea77 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -3106,6 +3106,10 @@ EXPORT_SYMBOL(__num_online_cpus);
 #ifdef CONFIG_PREFERRED_CPU
 struct cpumask __cpu_preferred_mask __read_mostly;
 EXPORT_SYMBOL_GPL(__cpu_preferred_mask);
+
+/* Serialize policy drivers; acquire inside cpus_read_lock(). */
+DEFINE_MUTEX(cpu_preferred_mutex);
+EXPORT_SYMBOL_GPL(cpu_preferred_mutex);
 #endif
 
 void init_cpu_present(const struct cpumask *src)
-- 
2.53.0


  parent reply	other threads:[~2026-11-01 19:22 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-01 19:21 [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Yury Norov
2026-11-01 19:21 ` [PATCH 1/6] sched: decouple PREFERRED_CPU from PARAVIRT in Kconfig.preempt Yury Norov
2026-11-01 19:28   ` sashiko-bot
2026-11-02 10:16   ` Ilya Leoshkevich
2026-11-02 11:00     ` Peter Zijlstra
2026-11-02 11:34       ` Ilya Leoshkevich
2026-11-02 13:00         ` Shrikanth Hegde
2026-11-02 13:41           ` Ilya Leoshkevich
2026-11-02 14:57             ` Shrikanth Hegde
2026-11-03  5:49             ` Shrikanth Hegde
2026-11-03 11:26               ` Ilya Leoshkevich
2026-11-03 11:30                 ` Ilya Leoshkevich
2026-11-01 19:21 ` [PATCH 2/6] cpumask: Add reset_preferred_cpumask() helper Yury Norov
2026-11-01 19:28   ` sashiko-bot
2026-11-01 19:21 ` [PATCH 3/6] sched: Restore preferred CPUs when hotplug removes the last one Yury Norov
2026-11-01 19:32   ` sashiko-bot
2026-11-05  9:05   ` Fushuai Wang
2026-11-05 13:27     ` Yury Norov
2026-11-01 19:22 ` Yury Norov [this message]
2026-11-01 19:32   ` [PATCH 4/6] sched: serialize preferred cpumask update better sashiko-bot
2026-11-01 19:22 ` [PATCH 5/6] virt: steal_governor: Warn on unexpected preferred mask states Yury Norov
2026-11-01 19:36   ` sashiko-bot
2026-11-01 19:22 ` [PATCH 6/6] cpu: Add per-CPU preferred sysfs control Yury Norov
2026-11-01 19:40   ` sashiko-bot
2026-11-02  8:47 ` [PATCH 0/6] sched: Expose writable interface for preferred CPUs mask Peter Zijlstra
2026-11-03 16:49   ` Yury Norov
2026-11-05 14:55     ` Peter Zijlstra
2026-11-06 17:34       ` Yury Norov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261101192203.6979-5-ynorov@nvidia.com \
    --to=ynorov@nvidia.com \
    --cc=agordeev@linux.ibm.com \
    --cc=arighi@nvidia.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=bsegall@google.com \
    --cc=corbet@lwn.net \
    --cc=dakr@kernel.org \
    --cc=dietmar.eggemann@arm.com \
    --cc=driver-core@lists.linux.dev \
    --cc=gor@linux.ibm.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hca@linux.ibm.com \
    --cc=johan@kernel.org \
    --cc=juri.lelli@redhat.com \
    --cc=kprateek.nayak@amd.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=meted@linux.ibm.com \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rafael@kernel.org \
    --cc=rdunlap@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=skhan@linuxfoundation.org \
    --cc=sshegde@linux.ibm.com \
    --cc=svens@linux.ibm.com \
    --cc=tglx@kernel.org \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    --cc=yury.norov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.