Linux Trace Kernel
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression
@ 2026-10-15 12:43 Peng Wang
  2026-10-15 12:43 ` [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks Peng Wang
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 12:43 UTC (permalink / raw)
  To: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner
  Cc: Peng Wang, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Peter Zijlstra, Waiman Long, Tejun Heo,
	He Rongguang, linux-kernel, linux-api, driver-core,
	linux-trace-kernel, cgroups

Workloads and their need for periodic ticks can change after boot.
This series lets userspace choose at runtime which CPUs in the boot-time
nohz_full set retain the non-idle scheduler tick and which are permitted
to stop it, while preserving the existing isolation configuration.

The first patch adds a per-CPU tick dependency; the second exposes a
sysfs CPU list. Permission defaults to all nohz_full CPUs. Revocation
uses the existing asynchronous kick. Idle tick suppression is unchanged,
and policy persists across hotplug.

Existing cpuset partition modes do not express this independent tick
policy. Feedback on the proposed interface is welcome.

Thanks,
Peng

Peng Wang (2):
  tick/nohz: Add a policy dependency for full dynticks
  cpu: Add sysfs control of full dynticks policy

 .../ABI/testing/sysfs-devices-system-cpu      | 40 ++++++++++++
 drivers/base/cpu.c                            | 46 ++++++++++++++
 include/linux/tick.h                          |  8 ++-
 include/trace/events/timer.h                  |  3 +-
 kernel/time/tick-sched.c                      | 62 +++++++++++++++++++
 5 files changed, 156 insertions(+), 3 deletions(-)


base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks
  2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
@ 2026-10-15 12:43 ` Peng Wang
  2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
  2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
  2 siblings, 0 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 12:43 UTC (permalink / raw)
  To: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner
  Cc: Peng Wang, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Peter Zijlstra, Waiman Long, Tejun Heo,
	He Rongguang, linux-kernel, linux-api, driver-core,
	linux-trace-kernel, cgroups

Workloads and their need for periodic ticks can change after boot.
Operators may need to retain the non-idle scheduler tick on selected
CPUs in the boot-time nohz_full set while permitting tick suppression
on others, without changing the isolation configuration.
The policy can be changed without taking CPUs offline.

Add a per-CPU POLICY dependency to inhibit non-idle tick suppression.
All nohz_full CPUs remain permitted by default. Revocation uses the
existing asynchronous kick; granting permission clears only POLICY.
Preserve the policy across hotplug and recognize it in tick_stop tracing.
Idle tick suppression is unchanged.

Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
---
 include/linux/tick.h         |  8 +++--
 include/trace/events/timer.h |  3 +-
 kernel/time/tick-sched.c     | 62 ++++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/include/linux/tick.h b/include/linux/tick.h
index b121c5d53e308..08d272dca0947 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -111,9 +111,10 @@ enum tick_dep_bits {
 	TICK_DEP_BIT_SCHED		= 2,
 	TICK_DEP_BIT_CLOCK_UNSTABLE	= 3,
 	TICK_DEP_BIT_RCU		= 4,
-	TICK_DEP_BIT_RCU_EXP		= 5
+	TICK_DEP_BIT_RCU_EXP		= 5,
+	TICK_DEP_BIT_POLICY		= 6
 };
-#define TICK_DEP_BIT_MAX TICK_DEP_BIT_RCU_EXP
+#define TICK_DEP_BIT_MAX TICK_DEP_BIT_POLICY
 
 #define TICK_DEP_MASK_NONE		0
 #define TICK_DEP_MASK_POSIX_TIMER	(1 << TICK_DEP_BIT_POSIX_TIMER)
@@ -122,6 +123,7 @@ enum tick_dep_bits {
 #define TICK_DEP_MASK_CLOCK_UNSTABLE	(1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
 #define TICK_DEP_MASK_RCU		(1 << TICK_DEP_BIT_RCU)
 #define TICK_DEP_MASK_RCU_EXP		(1 << TICK_DEP_BIT_RCU_EXP)
+#define TICK_DEP_MASK_POLICY		(1 << TICK_DEP_BIT_POLICY)
 
 #ifdef CONFIG_NO_HZ_COMMON
 extern bool tick_nohz_enabled;
@@ -205,6 +207,8 @@ extern void tick_nohz_dep_set_signal(struct task_struct *tsk,
 extern void tick_nohz_dep_clear_signal(struct signal_struct *signal,
 				       enum tick_dep_bits bit);
 extern bool tick_nohz_cpu_hotpluggable(unsigned int cpu);
+extern void tick_nohz_full_get_allowed(struct cpumask *mask);
+extern int tick_nohz_full_set_allowed(const struct cpumask *mask);
 
 /*
  * The below are tick_nohz_[set,clear]_dep() wrappers that optimize off-cases
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 3aa0608c63611..dff9579cd90eb 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -435,7 +435,8 @@ TRACE_EVENT(itimer_expire,
 		tick_dep_name(SCHED)			\
 		tick_dep_name(CLOCK_UNSTABLE)		\
 		tick_dep_name(RCU)			\
-		tick_dep_name_end(RCU_EXP)
+		tick_dep_name(RCU_EXP)			\
+		tick_dep_name_end(POLICY)
 
 #undef tick_dep_name
 #undef tick_dep_mask_name
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 6c3fea3867139..d76128cba985c 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -27,6 +27,7 @@
 #include <linux/posix-timers.h>
 #include <linux/context_tracking.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 
 #include <asm/irq_regs.h>
 
@@ -337,6 +338,7 @@ EXPORT_SYMBOL_GPL(tick_nohz_full_mask);
 bool tick_nohz_full_running;
 EXPORT_SYMBOL_GPL(tick_nohz_full_running);
 static atomic_t tick_dep_mask;
+static DEFINE_MUTEX(tick_nohz_full_policy_mutex);
 
 static bool check_tick_dependency(atomic_t *dep)
 {
@@ -375,6 +377,11 @@ static bool check_tick_dependency(atomic_t *dep)
 		return true;
 	}
 
+	if (val & TICK_DEP_MASK_POLICY) {
+		trace_tick_stop(0, TICK_DEP_MASK_POLICY);
+		return true;
+	}
+
 	return false;
 }
 
@@ -556,6 +563,57 @@ void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
 }
 EXPORT_SYMBOL_GPL(tick_nohz_dep_clear_cpu);
 
+/* Read policy, not whether a CPU currently has its tick stopped. */
+void tick_nohz_full_get_allowed(struct cpumask *mask)
+{
+	int cpu;
+
+	cpumask_clear(mask);
+	if (!tick_nohz_full_enabled())
+		return;
+
+	/* Exclude the reset of tick_cpu_sched during CPU teardown. */
+	cpus_read_lock();
+	mutex_lock(&tick_nohz_full_policy_mutex);
+	for_each_cpu(cpu, tick_nohz_full_mask) {
+		struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
+
+		if (!(atomic_read(&ts->tick_dep_mask) & TICK_DEP_MASK_POLICY))
+			cpumask_set_cpu(cpu, mask);
+	}
+	mutex_unlock(&tick_nohz_full_policy_mutex);
+	cpus_read_unlock();
+}
+
+int tick_nohz_full_set_allowed(const struct cpumask *mask)
+{
+	int cpu;
+
+	if (!tick_nohz_full_enabled())
+		return -EOPNOTSUPP;
+	if (!cpumask_subset(mask, tick_nohz_full_mask))
+		return -EINVAL;
+
+	cpus_read_lock();
+	mutex_lock(&tick_nohz_full_policy_mutex);
+	for_each_cpu(cpu, tick_nohz_full_mask) {
+		if (cpumask_test_cpu(cpu, mask)) {
+			tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_POLICY);
+		} else if (cpu_online(cpu)) {
+			/* The existing kick requests an asynchronous restart. */
+			tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_POLICY);
+		} else {
+			struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
+
+			/* Record policy without queuing irq_work on an offline CPU. */
+			atomic_or(TICK_DEP_MASK_POLICY, &ts->tick_dep_mask);
+		}
+	}
+	mutex_unlock(&tick_nohz_full_policy_mutex);
+	cpus_read_unlock();
+	return 0;
+}
+
 /*
  * Set a per-task tick dependency. RCU needs this. Also posix CPU timers
  * in order to elapse per task timers.
@@ -1528,6 +1586,7 @@ void tick_sched_timer_dying(int cpu)
 {
 	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
 	unsigned long idle_calls, idle_sleeps;
+	int policy;
 
 	/* This must happen before hrtimers are migrated! */
 	if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES))
@@ -1535,7 +1594,10 @@ void tick_sched_timer_dying(int cpu)
 
 	idle_calls = ts->idle_calls;
 	idle_sleeps = ts->idle_sleeps;
+	/* Preserve only the policy dependency across CPU offline/online. */
+	policy = atomic_read(&ts->tick_dep_mask) & TICK_DEP_MASK_POLICY;
 	memset(ts, 0, sizeof(*ts));
+	atomic_set(&ts->tick_dep_mask, policy);
 	ts->idle_calls = idle_calls;
 	ts->idle_sleeps = idle_sleeps;
 }

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
  2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
  2026-10-15 12:43 ` [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks Peng Wang
@ 2026-10-15 12:43 ` Peng Wang
  2026-10-15 16:07   ` Waiman Long
  2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
  2 siblings, 1 reply; 7+ messages in thread
From: Peng Wang @ 2026-10-15 12:43 UTC (permalink / raw)
  To: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner
  Cc: Peng Wang, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Peter Zijlstra, Waiman Long, Tejun Heo,
	He Rongguang, linux-kernel, linux-api, driver-core,
	linux-trace-kernel, cgroups

Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
nohz_full CPUs permitted to suppress their non-idle scheduler tick.

Writes replace the entire list; reads report policy, not current tick
state. Reject invalid input before updating policy. Document asynchronous
revocation, offline CPU configuration and persistence across hotplug.
The existing nohz_full attribute continues to report membership.

Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
---
 .../ABI/testing/sysfs-devices-system-cpu      | 40 ++++++++++++++++
 drivers/base/cpu.c                            | 46 +++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 82d10d556cc89..edf3408fd84c8 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -767,6 +767,46 @@ Description:	Preferred MTE tag checking mode
 
 		See also: Documentation/arch/arm64/memory-tagging-extension.rst
 
+What:		/sys/devices/system/cpu/nohz_full_allowed
+Date:		October 2026
+Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:
+		(RW) CPUs permitted to stop the scheduler tick while non-idle.
+		Available with CONFIG_NO_HZ_FULL. The default is the complete
+		nohz_full CPU list. Readback reports permission, not the current
+		tick state: all the usual tick dependencies still apply.
+
+		A write replaces the entire list, using CPU-list syntax (for
+		example, "1-3,5"). An empty line revokes permission from all
+		nohz_full CPUs. Invalid input is rejected without changing
+		policy. A parsed list containing CPUs outside nohz_full fails
+		with EINVAL. CPU numbers beyond the mask range and numeric
+		overflows are rejected by the CPU-list parser with ERANGE and
+		EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
+		bytes, otherwise E2BIG is returned. Embedded NULs and newlines
+		other than a trailing newline are rejected with EINVAL. Valid
+		writes without an active nohz_full configuration fail with
+		EOPNOTSUPP.
+
+		Reads fail with EOVERFLOW if the formatted output reaches
+		PAGE_SIZE - 1 bytes, rather than returning a potentially
+		truncated CPU list.
+
+		Revoking permission adds a per-CPU tick dependency. Online CPUs
+		are notified through the existing asynchronous kick mechanism
+		to restart a stopped non-idle tick. A successful write means
+		the policy is updated and any needed notification is queued;
+		it does not wait for tick restart. Changes to multiple CPUs
+		are not simultaneous. Granting permission only removes this
+		dependency and does not force the tick to stop.
+
+		Offline CPUs may be configured without sending notifications.
+		Policy persists across CPU offline/online. Idle tick suppression
+		is unchanged; the policy applies when a CPU leaves idle.
+
+		This interface does not change nohz_full membership, context
+		tracking, RCU offloading, or housekeeping configuration.
+
 What:		/sys/devices/system/cpu/nohz_full
 Date:		Apr 2015
 Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 69e52fed42415..299ce61cef895 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
 	return sysfs_emit(buf, "\n");
 }
 static DEVICE_ATTR_RO(nohz_full);
+
+static ssize_t nohz_full_allowed_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	cpumask_var_t mask;
+	ssize_t ret;
+
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	tick_nohz_full_get_allowed(mask);
+	ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
+
+	free_cpumask_var(mask);
+
+	/* Never present a truncated CPU list as the complete policy. */
+	return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
+}
+
+static ssize_t nohz_full_allowed_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	cpumask_var_t mask;
+	int ret;
+
+	/* kernfs may truncate an oversized write to PAGE_SIZE. */
+	if (count >= PAGE_SIZE)
+		return -E2BIG;
+	if (memchr(buf, '\0', count) ||
+	    (count > 1 && memchr(buf, '\n', count - 1)))
+		return -EINVAL;
+
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	ret = cpulist_parse(buf, mask);
+	if (!ret)
+		ret = tick_nohz_full_set_allowed(mask);
+
+	free_cpumask_var(mask);
+
+	return ret ? ret : count;
+}
+static DEVICE_ATTR_RW(nohz_full_allowed);
 #endif
 
 #ifdef CONFIG_CRASH_HOTPLUG
@@ -525,6 +570,7 @@ static struct attribute *cpu_root_attrs[] = {
 	&dev_attr_housekeeping.attr,
 #ifdef CONFIG_NO_HZ_FULL
 	&dev_attr_nohz_full.attr,
+	&dev_attr_nohz_full_allowed.attr,
 #endif
 #ifdef CONFIG_CRASH_HOTPLUG
 	&dev_attr_crash_hotplug.attr,

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression
  2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
  2026-10-15 12:43 ` [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks Peng Wang
  2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
@ 2026-10-15 16:00 ` Waiman Long
  2026-10-15 17:48   ` Peng Wang
  2 siblings, 1 reply; 7+ messages in thread
From: Waiman Long @ 2026-10-15 16:00 UTC (permalink / raw)
  To: Peng Wang, Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Peter Zijlstra, Tejun Heo, He Rongguang, linux-kernel, linux-api,
	driver-core, linux-trace-kernel, cgroups

On 10/15/26 8:43 AM, Peng Wang wrote:
> Workloads and their need for periodic ticks can change after boot.
> This series lets userspace choose at runtime which CPUs in the boot-time
> nohz_full set retain the non-idle scheduler tick and which are permitted
> to stop it, while preserving the existing isolation configuration.
>
> The first patch adds a per-CPU tick dependency; the second exposes a
> sysfs CPU list. Permission defaults to all nohz_full CPUs. Revocation
> uses the existing asynchronous kick. Idle tick suppression is unchanged,
> and policy persists across hotplug.
So you are basically setting up more nohz_full CPUs than the system 
actually needs to use at the moment and so want to disable nohz/tick 
part of nohz_full CPUs that don't need it. Can you elaborate more about 
the problems solve by introducing this new behavior?
>
> Existing cpuset partition modes do not express this independent tick
> policy. Feedback on the proposed interface is welcome.

We are planning to eventually extend cpuset partition mode to change 
nohz_full at runtime. This is still a work in progress.

Regards,
Longman

>
> Thanks,
> Peng
>
> Peng Wang (2):
>    tick/nohz: Add a policy dependency for full dynticks
>    cpu: Add sysfs control of full dynticks policy
>
>   .../ABI/testing/sysfs-devices-system-cpu      | 40 ++++++++++++
>   drivers/base/cpu.c                            | 46 ++++++++++++++
>   include/linux/tick.h                          |  8 ++-
>   include/trace/events/timer.h                  |  3 +-
>   kernel/time/tick-sched.c                      | 62 +++++++++++++++++++
>   5 files changed, 156 insertions(+), 3 deletions(-)
>
>
> base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
  2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
@ 2026-10-15 16:07   ` Waiman Long
  2026-10-15 17:50     ` Peng Wang
  0 siblings, 1 reply; 7+ messages in thread
From: Waiman Long @ 2026-10-15 16:07 UTC (permalink / raw)
  To: Peng Wang, Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Peter Zijlstra, Tejun Heo, He Rongguang, linux-kernel, linux-api,
	driver-core, linux-trace-kernel, cgroups


On 10/15/26 8:43 AM, Peng Wang wrote:
> Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
> nohz_full CPUs permitted to suppress their non-idle scheduler tick.
>
> Writes replace the entire list; reads report policy, not current tick
> state. Reject invalid input before updating policy. Document asynchronous
> revocation, offline CPU configuration and persistence across hotplug.
> The existing nohz_full attribute continues to report membership.
>
> Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
> Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
> Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
> ---
>   .../ABI/testing/sysfs-devices-system-cpu      | 40 ++++++++++++++++
>   drivers/base/cpu.c                            | 46 +++++++++++++++++++
>   2 files changed, 86 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
> index 82d10d556cc89..edf3408fd84c8 100644
> --- a/Documentation/ABI/testing/sysfs-devices-system-cpu
> +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
> @@ -767,6 +767,46 @@ Description:	Preferred MTE tag checking mode
>   
>   		See also: Documentation/arch/arm64/memory-tagging-extension.rst
>   
> +What:		/sys/devices/system/cpu/nohz_full_allowed

I do have a problem with the name of this sysfs file. nohz_full is more 
than just the tick. The naming may introduce the wrong impression that 
all nohz_full behavior can be controlled. May be a name like 
"nohz_tick_allowed" which is much more specific will be better.

Regards,
Longman

> +Date:		October 2026
> +Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
> +Description:
> +		(RW) CPUs permitted to stop the scheduler tick while non-idle.
> +		Available with CONFIG_NO_HZ_FULL. The default is the complete
> +		nohz_full CPU list. Readback reports permission, not the current
> +		tick state: all the usual tick dependencies still apply.
> +
> +		A write replaces the entire list, using CPU-list syntax (for
> +		example, "1-3,5"). An empty line revokes permission from all
> +		nohz_full CPUs. Invalid input is rejected without changing
> +		policy. A parsed list containing CPUs outside nohz_full fails
> +		with EINVAL. CPU numbers beyond the mask range and numeric
> +		overflows are rejected by the CPU-list parser with ERANGE and
> +		EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
> +		bytes, otherwise E2BIG is returned. Embedded NULs and newlines
> +		other than a trailing newline are rejected with EINVAL. Valid
> +		writes without an active nohz_full configuration fail with
> +		EOPNOTSUPP.
> +
> +		Reads fail with EOVERFLOW if the formatted output reaches
> +		PAGE_SIZE - 1 bytes, rather than returning a potentially
> +		truncated CPU list.
> +
> +		Revoking permission adds a per-CPU tick dependency. Online CPUs
> +		are notified through the existing asynchronous kick mechanism
> +		to restart a stopped non-idle tick. A successful write means
> +		the policy is updated and any needed notification is queued;
> +		it does not wait for tick restart. Changes to multiple CPUs
> +		are not simultaneous. Granting permission only removes this
> +		dependency and does not force the tick to stop.
> +
> +		Offline CPUs may be configured without sending notifications.
> +		Policy persists across CPU offline/online. Idle tick suppression
> +		is unchanged; the policy applies when a CPU leaves idle.
> +
> +		This interface does not change nohz_full membership, context
> +		tracking, RCU offloading, or housekeeping configuration.
> +
>   What:		/sys/devices/system/cpu/nohz_full
>   Date:		Apr 2015
>   Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index 69e52fed42415..299ce61cef895 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
>   	return sysfs_emit(buf, "\n");
>   }
>   static DEVICE_ATTR_RO(nohz_full);
> +
> +static ssize_t nohz_full_allowed_show(struct device *dev,
> +				      struct device_attribute *attr, char *buf)
> +{
> +	cpumask_var_t mask;
> +	ssize_t ret;
> +
> +	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> +		return -ENOMEM;
> +
> +	tick_nohz_full_get_allowed(mask);
> +	ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
> +
> +	free_cpumask_var(mask);
> +
> +	/* Never present a truncated CPU list as the complete policy. */
> +	return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
> +}
> +
> +static ssize_t nohz_full_allowed_store(struct device *dev,
> +				       struct device_attribute *attr,
> +				       const char *buf, size_t count)
> +{
> +	cpumask_var_t mask;
> +	int ret;
> +
> +	/* kernfs may truncate an oversized write to PAGE_SIZE. */
> +	if (count >= PAGE_SIZE)
> +		return -E2BIG;
> +	if (memchr(buf, '\0', count) ||
> +	    (count > 1 && memchr(buf, '\n', count - 1)))
> +		return -EINVAL;
> +
> +	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> +		return -ENOMEM;
> +
> +	ret = cpulist_parse(buf, mask);
> +	if (!ret)
> +		ret = tick_nohz_full_set_allowed(mask);
> +
> +	free_cpumask_var(mask);
> +
> +	return ret ? ret : count;
> +}
> +static DEVICE_ATTR_RW(nohz_full_allowed);
>   #endif
>   
>   #ifdef CONFIG_CRASH_HOTPLUG
> @@ -525,6 +570,7 @@ static struct attribute *cpu_root_attrs[] = {
>   	&dev_attr_housekeeping.attr,
>   #ifdef CONFIG_NO_HZ_FULL
>   	&dev_attr_nohz_full.attr,
> +	&dev_attr_nohz_full_allowed.attr,
>   #endif
>   #ifdef CONFIG_CRASH_HOTPLUG
>   	&dev_attr_crash_hotplug.attr,


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression
  2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
@ 2026-10-15 17:48   ` Peng Wang
  0 siblings, 0 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 17:48 UTC (permalink / raw)
  To: Waiman Long
  Cc: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Peter Zijlstra, Tejun Heo, He Rongguang,
	linux-kernel, linux-api, driver-core, linux-trace-kernel, cgroups

On Thu, Oct 15, 2026 at 12:00:25PM -0400, Waiman Long wrote:
> On 10/15/26 8:43 AM, Peng Wang wrote:
> > Workloads and their need for periodic ticks can change after boot.
> > This series lets userspace choose at runtime which CPUs in the boot-time
> > nohz_full set retain the non-idle scheduler tick and which are permitted
> > to stop it, while preserving the existing isolation configuration.
> > 
> > The first patch adds a per-CPU tick dependency; the second exposes a
> > sysfs CPU list. Permission defaults to all nohz_full CPUs. Revocation
> > uses the existing asynchronous kick. Idle tick suppression is unchanged,
> > and policy persists across hotplug.
> So you are basically setting up more nohz_full CPUs than the system actually
> needs to use at the moment and so want to disable nohz/tick part of
> nohz_full CPUs that don't need it. Can you elaborate more about the problems
> solve by introducing this new behavior?

Hi Waiman,

Yes. We have CPU-pinned workloads that benefit from reduced periodic
tick interference. The desired tick policy changes with CPU allocation.

With spare capacity, we allow selected nohz_full CPUs to stop their
tick. When capacity is fully allocated, we prefer to retain the
non-idle periodic tick across CPUs, avoiding an additional difference
in tick interference between housekeeping and nohz_full CPUs.
A CPU may still have only one runnable task in either case, so the
existing tick dependencies do not express this policy.

This series keeps the boot-time nohz_full CPU set, context tracking,
RCU offloading and housekeeping configuration unchanged. It only
controls whether those CPUs may stop their non-idle tick. The policy
can be changed without taking CPUs offline.

> > 
> > Existing cpuset partition modes do not express this independent tick
> > policy. Feedback on the proposed interface is welcome.
> 
> We are planning to eventually extend cpuset partition mode to change
> nohz_full at runtime. This is still a work in progress.

Thanks for mentioning the cpuset work. Would this tick-only policy
fit into that plan? The core mechanism in patch 1 is independent of
the sysfs interface.

Thanks,
Peng

> 
> Regards,
> Longman
> 
> > 
> > Thanks,
> > Peng
> > 
> > Peng Wang (2):
> >    tick/nohz: Add a policy dependency for full dynticks
> >    cpu: Add sysfs control of full dynticks policy
> > 
> >   .../ABI/testing/sysfs-devices-system-cpu      | 40 ++++++++++++
> >   drivers/base/cpu.c                            | 46 ++++++++++++++
> >   include/linux/tick.h                          |  8 ++-
> >   include/trace/events/timer.h                  |  3 +-
> >   kernel/time/tick-sched.c                      | 62 +++++++++++++++++++
> >   5 files changed, 156 insertions(+), 3 deletions(-)
> > 
> > 
> > base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy
  2026-10-15 16:07   ` Waiman Long
@ 2026-10-15 17:50     ` Peng Wang
  0 siblings, 0 replies; 7+ messages in thread
From: Peng Wang @ 2026-10-15 17:50 UTC (permalink / raw)
  To: Waiman Long
  Cc: Anna-Maria Behnsen, Frederic Weisbecker, Ingo Molnar,
	Thomas Gleixner, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Peter Zijlstra, Tejun Heo, He Rongguang,
	linux-kernel, linux-api, driver-core, linux-trace-kernel, cgroups

On Thu, Oct 15, 2026 at 12:07:14PM -0400, Waiman Long wrote:
> 
> On 10/15/26 8:43 AM, Peng Wang wrote:
> > Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
> > nohz_full CPUs permitted to suppress their non-idle scheduler tick.
> > 
> > Writes replace the entire list; reads report policy, not current tick
> > state. Reject invalid input before updating policy. Document asynchronous
> > revocation, offline CPU configuration and persistence across hotplug.
> > The existing nohz_full attribute continues to report membership.
> > 
> > Co-developed-by: He Rongguang <herongguang@linux.alibaba.com>
> > Signed-off-by: He Rongguang <herongguang@linux.alibaba.com>
> > Signed-off-by: Peng Wang <peng_wang@linux.alibaba.com>
> > ---
> >   .../ABI/testing/sysfs-devices-system-cpu      | 40 ++++++++++++++++
> >   drivers/base/cpu.c                            | 46 +++++++++++++++++++
> >   2 files changed, 86 insertions(+)
> > 
> > diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
> > index 82d10d556cc89..edf3408fd84c8 100644
> > --- a/Documentation/ABI/testing/sysfs-devices-system-cpu
> > +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
> > @@ -767,6 +767,46 @@ Description:	Preferred MTE tag checking mode
> >   		See also: Documentation/arch/arm64/memory-tagging-extension.rst
> > +What:		/sys/devices/system/cpu/nohz_full_allowed
> 
> I do have a problem with the name of this sysfs file. nohz_full is more than
> just the tick. The naming may introduce the wrong impression that all
> nohz_full behavior can be controlled. May be a name like "nohz_tick_allowed"
> which is much more specific will be better.

Hi Waiman,

Agreed, nohz_tick_allowed describes the scope more accurately.
If the control remains in sysfs, I'll use that name in the next version.

Thanks,
Peng

> 
> Regards,
> Longman
> 
> > +Date:		October 2026
> > +Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
> > +Description:
> > +		(RW) CPUs permitted to stop the scheduler tick while non-idle.
> > +		Available with CONFIG_NO_HZ_FULL. The default is the complete
> > +		nohz_full CPU list. Readback reports permission, not the current
> > +		tick state: all the usual tick dependencies still apply.
> > +
> > +		A write replaces the entire list, using CPU-list syntax (for
> > +		example, "1-3,5"). An empty line revokes permission from all
> > +		nohz_full CPUs. Invalid input is rejected without changing
> > +		policy. A parsed list containing CPUs outside nohz_full fails
> > +		with EINVAL. CPU numbers beyond the mask range and numeric
> > +		overflows are rejected by the CPU-list parser with ERANGE and
> > +		EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
> > +		bytes, otherwise E2BIG is returned. Embedded NULs and newlines
> > +		other than a trailing newline are rejected with EINVAL. Valid
> > +		writes without an active nohz_full configuration fail with
> > +		EOPNOTSUPP.
> > +
> > +		Reads fail with EOVERFLOW if the formatted output reaches
> > +		PAGE_SIZE - 1 bytes, rather than returning a potentially
> > +		truncated CPU list.
> > +
> > +		Revoking permission adds a per-CPU tick dependency. Online CPUs
> > +		are notified through the existing asynchronous kick mechanism
> > +		to restart a stopped non-idle tick. A successful write means
> > +		the policy is updated and any needed notification is queued;
> > +		it does not wait for tick restart. Changes to multiple CPUs
> > +		are not simultaneous. Granting permission only removes this
> > +		dependency and does not force the tick to stop.
> > +
> > +		Offline CPUs may be configured without sending notifications.
> > +		Policy persists across CPU offline/online. Idle tick suppression
> > +		is unchanged; the policy applies when a CPU leaves idle.
> > +
> > +		This interface does not change nohz_full membership, context
> > +		tracking, RCU offloading, or housekeeping configuration.
> > +
> >   What:		/sys/devices/system/cpu/nohz_full
> >   Date:		Apr 2015
> >   Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
> > diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> > index 69e52fed42415..299ce61cef895 100644
> > --- a/drivers/base/cpu.c
> > +++ b/drivers/base/cpu.c
> > @@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
> >   	return sysfs_emit(buf, "\n");
> >   }
> >   static DEVICE_ATTR_RO(nohz_full);
> > +
> > +static ssize_t nohz_full_allowed_show(struct device *dev,
> > +				      struct device_attribute *attr, char *buf)
> > +{
> > +	cpumask_var_t mask;
> > +	ssize_t ret;
> > +
> > +	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> > +		return -ENOMEM;
> > +
> > +	tick_nohz_full_get_allowed(mask);
> > +	ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
> > +
> > +	free_cpumask_var(mask);
> > +
> > +	/* Never present a truncated CPU list as the complete policy. */
> > +	return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
> > +}
> > +
> > +static ssize_t nohz_full_allowed_store(struct device *dev,
> > +				       struct device_attribute *attr,
> > +				       const char *buf, size_t count)
> > +{
> > +	cpumask_var_t mask;
> > +	int ret;
> > +
> > +	/* kernfs may truncate an oversized write to PAGE_SIZE. */
> > +	if (count >= PAGE_SIZE)
> > +		return -E2BIG;
> > +	if (memchr(buf, '\0', count) ||
> > +	    (count > 1 && memchr(buf, '\n', count - 1)))
> > +		return -EINVAL;
> > +
> > +	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> > +		return -ENOMEM;
> > +
> > +	ret = cpulist_parse(buf, mask);
> > +	if (!ret)
> > +		ret = tick_nohz_full_set_allowed(mask);
> > +
> > +	free_cpumask_var(mask);
> > +
> > +	return ret ? ret : count;
> > +}
> > +static DEVICE_ATTR_RW(nohz_full_allowed);
> >   #endif
> >   #ifdef CONFIG_CRASH_HOTPLUG
> > @@ -525,6 +570,7 @@ static struct attribute *cpu_root_attrs[] = {
> >   	&dev_attr_housekeeping.attr,
> >   #ifdef CONFIG_NO_HZ_FULL
> >   	&dev_attr_nohz_full.attr,
> > +	&dev_attr_nohz_full_allowed.attr,
> >   #endif
> >   #ifdef CONFIG_CRASH_HOTPLUG
> >   	&dev_attr_crash_hotplug.attr,
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-15 17:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 12:43 [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Peng Wang
2026-10-15 12:43 ` [RFC PATCH 1/2] tick/nohz: Add a policy dependency for full dynticks Peng Wang
2026-10-15 12:43 ` [RFC PATCH 2/2] cpu: Add sysfs control of full dynticks policy Peng Wang
2026-10-15 16:07   ` Waiman Long
2026-10-15 17:50     ` Peng Wang
2026-10-15 16:00 ` [RFC PATCH 0/2] tick/nohz: Add runtime control of non-idle tick suppression Waiman Long
2026-10-15 17:48   ` Peng Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox