* [PATCH] sched: Replace nr_iowait_cpu() with a bool accessor
@ 2026-10-14 13:47 ` Christian Loehle
0 siblings, 0 replies; 3+ messages in thread
From: Christian Loehle @ 2026-10-14 13:47 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot
Cc: Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
Valentin Schneider, K Prateek Nayak, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Julia Lawall, Nicolas Palix, linux-s390,
linux-kernel, cocci, Christian Loehle
The menu governor was the last consumer of the per-CPU I/O-wait count
that needed its magnitude, apart from nr_iowait() summing it globally.
Commit 38f83090f515 ("cpuidle: menu: Remove iowait influence") removed
that use. All remaining per-CPU consumers only test for zero/nonzero.
Replace nr_iowait_cpu() with bool cpu_has_iowait() and update the generic
and s390 idle accounting callers. Have nr_iowait() read the counters
directly so that the global total and existing accounting are preserved.
Replace the stale menu comment with a description of the predicate.
Include the Coccinelle recipe for the code conversion, verified against
the original files. The helper's comment is updated manually. Reproduce
the conversion with:
make coccicheck COCCI=scripts/coccinelle/api/cpu_has_iowait.cocci MODE=patch
Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
arch/s390/kernel/idle.c | 4 +-
include/linux/sched/stat.h | 2 +-
kernel/sched/core.c | 13 ++---
kernel/sched/cputime.c | 10 ++--
scripts/coccinelle/api/cpu_has_iowait.cocci | 56 +++++++++++++++++++++
5 files changed, 69 insertions(+), 16 deletions(-)
create mode 100644 scripts/coccinelle/api/cpu_has_iowait.cocci
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
index dd12efb58201..ff9732ef494c 100644
--- a/arch/s390/kernel/idle.c
+++ b/arch/s390/kernel/idle.c
@@ -82,13 +82,13 @@ static u64 arch_cpu_idle_time(int cpu, enum cpu_usage_stat idx, bool compute_del
u64 arch_kcpustat_field_idle(int cpu)
{
- return arch_cpu_idle_time(cpu, CPUTIME_IDLE, !nr_iowait_cpu(cpu));
+ return arch_cpu_idle_time(cpu, CPUTIME_IDLE, !cpu_has_iowait(cpu));
}
EXPORT_SYMBOL_GPL(arch_kcpustat_field_idle);
u64 arch_kcpustat_field_iowait(int cpu)
{
- return arch_cpu_idle_time(cpu, CPUTIME_IOWAIT, nr_iowait_cpu(cpu));
+ return arch_cpu_idle_time(cpu, CPUTIME_IOWAIT, cpu_has_iowait(cpu));
}
EXPORT_SYMBOL_GPL(arch_kcpustat_field_iowait);
diff --git a/include/linux/sched/stat.h b/include/linux/sched/stat.h
index 0108a38bb64d..4810b14d0372 100644
--- a/include/linux/sched/stat.h
+++ b/include/linux/sched/stat.h
@@ -20,7 +20,7 @@ extern int nr_processes(void);
extern unsigned int nr_running(void);
extern bool single_task_running(void);
extern unsigned int nr_iowait(void);
-extern unsigned int nr_iowait_cpu(int cpu);
+extern bool cpu_has_iowait(int cpu);
static inline int sched_info_on(void)
{
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 1fe40de6ebe3..1bde5187dafd 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5588,15 +5588,12 @@ unsigned long long nr_context_switches(void)
}
/*
- * Consumers of these two interfaces, like for example the cpuidle menu
- * governor, are using nonsensical data. Preferring shallow idle state selection
- * for a CPU that has IO-wait which might not even end up running the task when
- * it does become runnable.
+ * Return whether any tasks are accounted as I/O waiters on this CPU.
+ * They may wake up on a different CPU.
*/
-
-unsigned int nr_iowait_cpu(int cpu)
+bool cpu_has_iowait(int cpu)
{
- return atomic_read(&cpu_rq(cpu)->nr_iowait);
+ return atomic_read(&cpu_rq(cpu)->nr_iowait) != 0;
}
/*
@@ -5634,7 +5631,7 @@ unsigned int nr_iowait(void)
unsigned int i, sum = 0;
for_each_possible_cpu(i)
- sum += nr_iowait_cpu(i);
+ sum += atomic_read(&cpu_rq(i)->nr_iowait);
return sum;
}
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 06bddaa738e5..1f84a950abed 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -431,7 +431,7 @@ static void kcpustat_idle_stop(struct kernel_cpustat *kc, u64 now)
if (!kc->idle_elapse)
return;
- iowait = nr_iowait_cpu(smp_processor_id()) > 0;
+ iowait = cpu_has_iowait(smp_processor_id());
delta = now - kc->idle_entrytime;
steal = steal_account_process_time(delta);
@@ -544,14 +544,14 @@ static u64 kcpustat_field_dyntick(int cpu, enum cpu_usage_stat idx,
u64 kcpustat_field_idle(int cpu)
{
return kcpustat_field_dyntick(cpu, CPUTIME_IDLE,
- !nr_iowait_cpu(cpu), ktime_get());
+ !cpu_has_iowait(cpu), ktime_get());
}
EXPORT_SYMBOL_GPL(kcpustat_field_idle);
u64 kcpustat_field_iowait(int cpu)
{
return kcpustat_field_dyntick(cpu, CPUTIME_IOWAIT,
- nr_iowait_cpu(cpu), ktime_get());
+ cpu_has_iowait(cpu), ktime_get());
}
EXPORT_SYMBOL_GPL(kcpustat_field_iowait);
#else
@@ -601,7 +601,7 @@ static u64 get_cpu_sleep_time_us(int cpu, enum cpu_usage_stat idx,
u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
{
return get_cpu_sleep_time_us(cpu, CPUTIME_IDLE,
- !nr_iowait_cpu(cpu), last_update_time);
+ !cpu_has_iowait(cpu), last_update_time);
}
EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
@@ -625,7 +625,7 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
{
return get_cpu_sleep_time_us(cpu, CPUTIME_IOWAIT,
- nr_iowait_cpu(cpu), last_update_time);
+ cpu_has_iowait(cpu), last_update_time);
}
EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
diff --git a/scripts/coccinelle/api/cpu_has_iowait.cocci b/scripts/coccinelle/api/cpu_has_iowait.cocci
new file mode 100644
index 000000000000..cc903b1d2586
--- /dev/null
+++ b/scripts/coccinelle/api/cpu_has_iowait.cocci
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Replace nr_iowait_cpu() with a boolean accessor after menu stopped using
+// the per-CPU count. Preserve the count used by nr_iowait().
+//
+// The accompanying update to the helper's comment is manual.
+//
+// Options: --include-headers
+
+virtual patch
+
+@ definition depends on patch @
+identifier cpu;
+typedef bool;
+@@
+
+- unsigned int nr_iowait_cpu(int cpu)
++ bool cpu_has_iowait(int cpu)
+ {
+- return atomic_read(&cpu_rq(cpu)->nr_iowait);
++ return atomic_read(&cpu_rq(cpu)->nr_iowait) != 0;
+ }
+
+@ prototype_rule depends on patch @
+identifier cpu;
+typedef bool;
+@@
+
+- extern unsigned int nr_iowait_cpu
++ extern bool cpu_has_iowait
+ (int cpu);
+
+@ total depends on patch @
+expression cpu;
+@@
+
+ unsigned int nr_iowait(void)
+ {
+ <...
+- nr_iowait_cpu(cpu)
++ atomic_read(&cpu_rq(cpu)->nr_iowait)
+ ...>
+ }
+
+@ predicate depends on patch @
+expression cpu;
+@@
+
+- nr_iowait_cpu(cpu) > 0
++ cpu_has_iowait(cpu)
+
+@ callers depends on patch @
+expression cpu;
+@@
+
+- nr_iowait_cpu(cpu)
++ cpu_has_iowait(cpu)
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [cocci] [PATCH] sched: Replace nr_iowait_cpu() with a bool accessor
@ 2026-10-14 13:47 ` Christian Loehle
0 siblings, 0 replies; 3+ messages in thread
From: Christian Loehle @ 2026-10-14 13:47 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot
Cc: Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
Valentin Schneider, K Prateek Nayak, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Julia Lawall, Nicolas Palix, linux-s390,
linux-kernel, cocci, Christian Loehle
The menu governor was the last consumer of the per-CPU I/O-wait count
that needed its magnitude, apart from nr_iowait() summing it globally.
Commit 38f83090f515 ("cpuidle: menu: Remove iowait influence") removed
that use. All remaining per-CPU consumers only test for zero/nonzero.
Replace nr_iowait_cpu() with bool cpu_has_iowait() and update the generic
and s390 idle accounting callers. Have nr_iowait() read the counters
directly so that the global total and existing accounting are preserved.
Replace the stale menu comment with a description of the predicate.
Include the Coccinelle recipe for the code conversion, verified against
the original files. The helper's comment is updated manually. Reproduce
the conversion with:
make coccicheck COCCI=scripts/coccinelle/api/cpu_has_iowait.cocci MODE=patch
Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
arch/s390/kernel/idle.c | 4 +-
include/linux/sched/stat.h | 2 +-
kernel/sched/core.c | 13 ++---
kernel/sched/cputime.c | 10 ++--
scripts/coccinelle/api/cpu_has_iowait.cocci | 56 +++++++++++++++++++++
5 files changed, 69 insertions(+), 16 deletions(-)
create mode 100644 scripts/coccinelle/api/cpu_has_iowait.cocci
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
index dd12efb58201..ff9732ef494c 100644
--- a/arch/s390/kernel/idle.c
+++ b/arch/s390/kernel/idle.c
@@ -82,13 +82,13 @@ static u64 arch_cpu_idle_time(int cpu, enum cpu_usage_stat idx, bool compute_del
u64 arch_kcpustat_field_idle(int cpu)
{
- return arch_cpu_idle_time(cpu, CPUTIME_IDLE, !nr_iowait_cpu(cpu));
+ return arch_cpu_idle_time(cpu, CPUTIME_IDLE, !cpu_has_iowait(cpu));
}
EXPORT_SYMBOL_GPL(arch_kcpustat_field_idle);
u64 arch_kcpustat_field_iowait(int cpu)
{
- return arch_cpu_idle_time(cpu, CPUTIME_IOWAIT, nr_iowait_cpu(cpu));
+ return arch_cpu_idle_time(cpu, CPUTIME_IOWAIT, cpu_has_iowait(cpu));
}
EXPORT_SYMBOL_GPL(arch_kcpustat_field_iowait);
diff --git a/include/linux/sched/stat.h b/include/linux/sched/stat.h
index 0108a38bb64d..4810b14d0372 100644
--- a/include/linux/sched/stat.h
+++ b/include/linux/sched/stat.h
@@ -20,7 +20,7 @@ extern int nr_processes(void);
extern unsigned int nr_running(void);
extern bool single_task_running(void);
extern unsigned int nr_iowait(void);
-extern unsigned int nr_iowait_cpu(int cpu);
+extern bool cpu_has_iowait(int cpu);
static inline int sched_info_on(void)
{
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 1fe40de6ebe3..1bde5187dafd 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5588,15 +5588,12 @@ unsigned long long nr_context_switches(void)
}
/*
- * Consumers of these two interfaces, like for example the cpuidle menu
- * governor, are using nonsensical data. Preferring shallow idle state selection
- * for a CPU that has IO-wait which might not even end up running the task when
- * it does become runnable.
+ * Return whether any tasks are accounted as I/O waiters on this CPU.
+ * They may wake up on a different CPU.
*/
-
-unsigned int nr_iowait_cpu(int cpu)
+bool cpu_has_iowait(int cpu)
{
- return atomic_read(&cpu_rq(cpu)->nr_iowait);
+ return atomic_read(&cpu_rq(cpu)->nr_iowait) != 0;
}
/*
@@ -5634,7 +5631,7 @@ unsigned int nr_iowait(void)
unsigned int i, sum = 0;
for_each_possible_cpu(i)
- sum += nr_iowait_cpu(i);
+ sum += atomic_read(&cpu_rq(i)->nr_iowait);
return sum;
}
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 06bddaa738e5..1f84a950abed 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -431,7 +431,7 @@ static void kcpustat_idle_stop(struct kernel_cpustat *kc, u64 now)
if (!kc->idle_elapse)
return;
- iowait = nr_iowait_cpu(smp_processor_id()) > 0;
+ iowait = cpu_has_iowait(smp_processor_id());
delta = now - kc->idle_entrytime;
steal = steal_account_process_time(delta);
@@ -544,14 +544,14 @@ static u64 kcpustat_field_dyntick(int cpu, enum cpu_usage_stat idx,
u64 kcpustat_field_idle(int cpu)
{
return kcpustat_field_dyntick(cpu, CPUTIME_IDLE,
- !nr_iowait_cpu(cpu), ktime_get());
+ !cpu_has_iowait(cpu), ktime_get());
}
EXPORT_SYMBOL_GPL(kcpustat_field_idle);
u64 kcpustat_field_iowait(int cpu)
{
return kcpustat_field_dyntick(cpu, CPUTIME_IOWAIT,
- nr_iowait_cpu(cpu), ktime_get());
+ cpu_has_iowait(cpu), ktime_get());
}
EXPORT_SYMBOL_GPL(kcpustat_field_iowait);
#else
@@ -601,7 +601,7 @@ static u64 get_cpu_sleep_time_us(int cpu, enum cpu_usage_stat idx,
u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
{
return get_cpu_sleep_time_us(cpu, CPUTIME_IDLE,
- !nr_iowait_cpu(cpu), last_update_time);
+ !cpu_has_iowait(cpu), last_update_time);
}
EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
@@ -625,7 +625,7 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
{
return get_cpu_sleep_time_us(cpu, CPUTIME_IOWAIT,
- nr_iowait_cpu(cpu), last_update_time);
+ cpu_has_iowait(cpu), last_update_time);
}
EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
diff --git a/scripts/coccinelle/api/cpu_has_iowait.cocci b/scripts/coccinelle/api/cpu_has_iowait.cocci
new file mode 100644
index 000000000000..cc903b1d2586
--- /dev/null
+++ b/scripts/coccinelle/api/cpu_has_iowait.cocci
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Replace nr_iowait_cpu() with a boolean accessor after menu stopped using
+// the per-CPU count. Preserve the count used by nr_iowait().
+//
+// The accompanying update to the helper's comment is manual.
+//
+// Options: --include-headers
+
+virtual patch
+
+@ definition depends on patch @
+identifier cpu;
+typedef bool;
+@@
+
+- unsigned int nr_iowait_cpu(int cpu)
++ bool cpu_has_iowait(int cpu)
+ {
+- return atomic_read(&cpu_rq(cpu)->nr_iowait);
++ return atomic_read(&cpu_rq(cpu)->nr_iowait) != 0;
+ }
+
+@ prototype_rule depends on patch @
+identifier cpu;
+typedef bool;
+@@
+
+- extern unsigned int nr_iowait_cpu
++ extern bool cpu_has_iowait
+ (int cpu);
+
+@ total depends on patch @
+expression cpu;
+@@
+
+ unsigned int nr_iowait(void)
+ {
+ <...
+- nr_iowait_cpu(cpu)
++ atomic_read(&cpu_rq(cpu)->nr_iowait)
+ ...>
+ }
+
+@ predicate depends on patch @
+expression cpu;
+@@
+
+- nr_iowait_cpu(cpu) > 0
++ cpu_has_iowait(cpu)
+
+@ callers depends on patch @
+expression cpu;
+@@
+
+- nr_iowait_cpu(cpu)
++ cpu_has_iowait(cpu)
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] sched: Replace nr_iowait_cpu() with a bool accessor
2026-10-14 13:47 ` [cocci] " Christian Loehle
(?)
@ 2026-10-14 13:53 ` sashiko-bot
-1 siblings, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-10-14 13:53 UTC (permalink / raw)
To: Christian Loehle
Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger
> The menu governor was the last consumer of the per-CPU I/O-wait count
> that needed its magnitude, apart from nr_iowait() summing it globally.
> Commit 38f83090f515 ("cpuidle: menu: Remove iowait influence") removed
> that use. All remaining per-CPU consumers only test for zero/nonzero.
>
> Replace nr_iowait_cpu() with bool cpu_has_iowait() and update the generic
> and s390 idle accounting callers. Have nr_iowait() read the counters
> directly so that the global total and existing accounting are preserved.
> Replace the stale menu comment with a description of the predicate.
>
> Include the Coccinelle recipe for the code conversion, verified against
> the original files. The helper's comment is updated manually. Reproduce
> the conversion with:
>
> make coccicheck COCCI=scripts/coccinelle/api/cpu_has_iowait.cocci MODE=patch
>
> Signed-off-by: Christian Loehle <christian.loehle@arm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261014134745.3032405-1-christian.loehle@arm.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-14 14:19 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 13:47 [PATCH] sched: Replace nr_iowait_cpu() with a bool accessor Christian Loehle
2026-10-14 13:47 ` [cocci] " Christian Loehle
2026-10-14 13:53 ` sashiko-bot
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.